diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 06374c0df..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -name: "\U0001F577 Bug report" -about: Report a bug. -title: '' -labels: ":spider: type-bug" -assignees: Danielku15 - ---- - - - -### Expected Results - - -### Observed Results - - -### Steps to Reproduce - - -Link to jsFiddle, CodePen, Project etc.: - -1. -2. -3. - -### Further details - - -### Your environment - -**Version** -- [ ] 1.0 -- [ ] 1.1 -- [ ] 1.2-alpha.## - -**Flavor** -- [ ] JavaScript -- [ ] .net - -**System** - \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report_form.yml b/.github/ISSUE_TEMPLATE/bug_report_form.yml new file mode 100644 index 000000000..b62cdbba3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_form.yml @@ -0,0 +1,100 @@ +name: 🕷️ Bug Report +description: Report a bug. +labels: "state-needs-triage" +assignees: Danielku15 +body: +- type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true +- type: textarea + id: current + attributes: + label: Current Behavior + description: A concise description of what you're experiencing. + validations: + required: true +- type: textarea + id: expected + attributes: + label: Expected Behavior + description: A concise description of what you expected to happen. + validations: + required: true +- type: textarea + id: steps + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. + 2. + 3. + 4. + validations: + required: true +- type: input + id: link + attributes: + label: Link to jsFiddle, CodePen, Project + description: Providing a minimal reproducible example can help a lot. + validations: + required: false +- type: dropdown + id: version + attributes: + label: Found in Version + description: Which version of alphaTab are you using? + options: + - 1.3-alpha + - 1.2 + - 1.1 + - 1.0 + - Other + validations: + required: true +- type: dropdown + id: platform + attributes: + label: Platform + description: On which platform are you using alphaTab? + options: + - Web + - Node.js + - .net (WPF) + - .net (WinForms) + - .net (Other) + - Android (WebView) + - Android (Native) + - iOS (WebView) + - Other + validations: + required: true +- type: textarea + id: environment + attributes: + label: Environment + description: | + examples: + - **OS**: Windows 10 Pro + - **Browser**: Chrome 92.0.4515.159 + value: | + - **OS**: + - **Browser**: + - **.net Version**: + render: markdown + validations: + required: true +- type: textarea + id: further + attributes: + label: Anything else? + description: | + Links? References? Anything that will give us more context about the issue you are encountering! + + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. + validations: + required: false diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..ebcaebda0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + + - package-ecosystem: "nuget" + directory: "/src.csharp" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54e3610ca..014409262 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,14 +5,15 @@ on: - develop - master pull_request: + workflow_dispatch: jobs: build_web: name: Build and Test Web - runs-on: windows-latest + runs-on: windows-2022 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: '12.x' - run: npm install @@ -21,15 +22,16 @@ jobs: build_csharp: name: Build and Test C# - runs-on: windows-latest + runs-on: windows-2022 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: '12.x' - uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.100' + dotnet-version: | + 6.0.x - run: npm install - run: npm run build-csharp-ci - - run: npm run test-csharp-ci \ No newline at end of file + - run: npm run test-csharp-ci diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 000000000..927de5a46 --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,22 @@ +name: Dependabot auto-merge +on: pull_request + +permissions: + pull-requests: write + contents: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.1.1 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Enable auto-merge for Dependabot PRs + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dafb89f05..a7a8bc191 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,50 +1,103 @@ name: Publish on: - push: - branches: - - develop - + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + jobs: nighty_web: name: Web - runs-on: windows-latest + runs-on: windows-2022 steps: - # Checkout the repo - - uses: actions/checkout@v2 + - name: Create cache file + run: | + mkdir check-sha + echo ${{ github.sha }} >> github-sha.txt + + - name: Check SHA + id: check_sha + uses: actions/cache@v2 + with: + path: check-sha + key: check-sha-${{ github.sha }} + + - name: Checkout the repo + if: steps.check_sha.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + + - name: Setup Node + if: steps.check_sha.outputs.cache-hit != 'true' + uses: actions/setup-node@v2 + with: + node-version: '16' - # Build Project - - uses: actions/setup-node@master - name: Build Project + if: steps.check_sha.outputs.cache-hit != 'true' run: | npm install node ./scripts/update-version.js alpha ${{github.run_number}} npm run build-ci - - # Publish to GitHub Package Registry - - uses: actions/setup-node@master + + - uses: actions/setup-node@v2 + if: steps.check_sha.outputs.cache-hit != 'true' with: - node-version: '12.x' + node-version: '16' registry-url: https://registry.npmjs.org/ - - name: Publish to GitHub Package Registry (alpha) + + - name: Publish to NPM (alpha) + if: steps.check_sha.outputs.cache-hit != 'true' run: npm publish --access public --tag alpha env: NODE_AUTH_TOKEN: ${{secrets.NPMJS_AUTH_TOKEN}} - + nightly_csharp: name: C# - runs-on: windows-latest + runs-on: windows-2022 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - name: Create cache file + run: | + mkdir check-sha + echo ${{ github.sha }} >> github-sha.txt + + - name: Check SHA + id: check_sha + uses: actions/cache@v2 with: - node-version: '12.x' - - uses: actions/setup-dotnet@v1 + path: check-sha + key: check-sha-${{ github.sha }} + + - name: Checkout the repo + if: steps.check_sha.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + + - name: Setup Node + if: steps.check_sha.outputs.cache-hit != 'true' + uses: actions/setup-node@v2 with: - dotnet-version: '3.1.100' - env: - NUGET_AUTH_TOKEN: ${{secrets.NUGET_API_KEY}} + node-version: '16' + + - name: Setup DotNet + if: steps.check_sha.outputs.cache-hit != 'true' + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 6.0.x + - run: npm install - - run: node ./scripts/update-csharp-version.js alpha ${{github.run_number}} - - run: npm run build-csharp-ci - - run: dotnet nuget push src.csharp\AlphaTab\bin\Release\*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json - - run: dotnet nuget push src.csharp\AlphaTab.Windows\bin\Release\*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json + if: steps.check_sha.outputs.cache-hit != 'true' + + - name: Update C# Version + if: steps.check_sha.outputs.cache-hit != 'true' + run: node ./scripts/update-csharp-version.js alpha ${{github.run_number}} + + - name: Build Project + if: steps.check_sha.outputs.cache-hit != 'true' + run: npm run build-csharp-ci + + - name: Publish AlphaTab.nupkg + if: steps.check_sha.outputs.cache-hit != 'true' + run: dotnet nuget push src.csharp\AlphaTab\bin\Release\*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json + + - name: Publish AlphaTab.Windows.nupkg + if: steps.check_sha.outputs.cache-hit != 'true' + run: dotnet nuget push src.csharp\AlphaTab.Windows\bin\Release\*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 606ba4a82..e078e2b8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: jobs: release_web: name: Web - runs-on: windows-latest + runs-on: windows-2022 steps: # Checkout the repo - uses: actions/checkout@v2 @@ -32,7 +32,7 @@ jobs: release_csharp: name: C# - runs-on: windows-latest + runs-on: windows-2022 steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 @@ -40,7 +40,8 @@ jobs: node-version: '12.x' - uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.100' + dotnet-version: | + 6.0.x env: NUGET_AUTH_TOKEN: ${{secrets.NUGET_API_KEY}} - run: npm install diff --git a/.gitignore b/.gitignore index 87b275052..90b8ed2e6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,11 @@ bin/ *.tgz test-results/ debug.log -src/generated/VersionInfo.ts \ No newline at end of file +src/generated/VersionInfo.ts +.gradle +build/ +gradle-app.setting +!gradle-wrapper.jar +.gradletasknamecache +**/build/ +local.properties \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bb07df5f4..6e21eb897 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,11 +2,28 @@ I am happy that you are interested in alphaTab and want to contribute by entering bugs, feature requests, asking questions or even contribute code. Please play with the rules. It's not only about what you say, but also how you say it. Playing nice increases the chance of getting features/bugfixes faster :wink: Remember that everything you get here is for free and in the end it's about giving and taking. -## Before entering an issue +## Discussions vs Issues + +We consider the issues our concerete work backlog. That means any item there should be on a quality level that it allows working on a topic. +Discussions are more a playground for talking about ideas, features or problems before we actually derive a work item from it. + +Here some guidance which might help you deciding whether to open a issue or a discussion post: + +Open a Discussion if: +* You have an idea about a new feature you know alphaTab does not have yet. +* You need support in using alphaTab. +* You are not sure if alphaTab can do something you need it to do. +* AlphaTab does not behave as you would maybe expect it to behave, but you aren't yet sure if alphaTab or your usage is the problem cause. + +Open an Issue if: +* You found a very obvious bug that something is not working. You can reproduce the issue and provide us the info how we can also reproduce it. +* You found that something is missing on an existing feature and you want to have it extended. + +## When entering an issue **Please follow the provided templates when entering issues. It is crucial to provide the asked information to reduce the effort on our side to handle all the incoming requests. We see a strong tendency of people not providing the asked information and we need to make multiple rounds to find out first what's happening on their side. It should be possible for every developer to take 2 additional minutes of time to enter issues in a proper structured way and by this reduce a multiple of this time on our side.** -**We will close issues not following the template without further discussion.** +**We will close issues not following the template or clean structure without further discussion.** Beside that: @@ -16,5 +33,24 @@ Beside that: ## Contributing Code -Code changes can be offered by opening pull requests. Fork alphaTab, add your changes and file a pull request. -When adding changes to alphaTab ensure they are compiling and working on all platforms. \ No newline at end of file +Code changes can be offered by opening pull requests. To do so, we recommend following workflow: + +1. Start with [forking](https://docs.github.com/en/get-started/quickstart/fork-a-repo) this repository. +This way you get a copy of our repository in your account where you can work. +2. Create a new feature branch starting from `develop` on which you add your changes. +We recommend branch names like `feature/` (e.g. feature/alphatex-alternate-endings) or `feature/` (e.g. feature/issue-1234). +3. If you have your changes ready, [open a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) against the main repository. +This way you make your changes visible to us. Be sure to fill out the template. +4. When you think your pull request is not yet fully ready, mark it as a [draft pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests). +5. As soon you think your changes are ready, clear the draft state. This way it should become visible on our side for review. +6. We will then review the code, and ensure that the CI system builds and runs your changes. +7. We might ask for changes to the code style or feature depending to fulfill our guidelines and needs. +8. If everything goes well, we will approve the change and merge it into the product. +9. Once we will release a new version, we will of course mention you als contributor of the particular bugfix or feature ;) + +If you are new to contributing to Open Source Projects on GitHub you might read through some articles in the web. The principle is usually always very similar, projects just might have different rules to follow. + + +https://docs.github.com/en/get-started/quickstart/contributing-to-projects +https://opensource.com/article/19/7/create-pull-request-github +https://www.freecodecamp.org/news/how-to-make-your-first-pull-request-on-github-3/ \ No newline at end of file diff --git a/README.md b/README.md index b956d5b3f..b192ee1b5 100644 --- a/README.md +++ b/README.md @@ -17,42 +17,52 @@ To get started follow our guides and tutorials at: ## Build Status -> Until the official 1.0 release we recommend to use pre release versions based on the `develop` branch. -   |   --- | --- **Build** | ![Build](https://github.com/CoderLine/alphaTab/workflows/Build/badge.svg?branch=develop) -**Documentation** | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www2.alphatab.net/) - -# Downloads - -The latest binaries based are available for download at either npmjs.org or NuGet.org. -Use the links below to grab the binaries from the latest builds. We recommend using package managers to pull the files to your projects. - -  |   ---- | --- | -**JavaScript** | [NPM](https://www.npmjs.com/package/@coderline/alphatab) -**.net** | [NuGet](https://www.nuget.org/profiles/CoderLine) +**Documentation** | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.alphatab.net/) # Features -alphaTab mostly focuses on web based platforms allowing music notation to be embedded into websites and browser based apps but is designed to be used also from .net based platforms like Windows, UWP and Xamarin. +alphaTab mostly focuses on web based platforms allowing music notation to be embedded into websites and browser based apps but is designed to be used also from various other platforms like .net and Android either as a platform native integration or through runtime specific JavaScript engines. alphaTab can load music notation from various sources like Guitar Pro 3-7, AlphaTex and MusicXML (experimental) and render them into beautiful music sheets right within your browser (or application). Using a built in midi synthesizer named alphaSynth the music sheets can also be played in your browser. -* load GuitarPro 3-5, GuitarPro 6, AlphaTex or MusicXML (experimental) -* render as SVG, HTML5 canvas, GDI+,... +* load GuitarPro 3-5, GuitarPro 6, Guitar Pro 7, AlphaTex or MusicXML (experimental) +* render as SVG or Raster Graphics (raster graphics depends on platform: HTML5 canvas, GDI+, SkiaSharp, Android Canvas)... * display single or multiple instruments as standard music notation and guitar tablatures consisting of song information, repeats, alternate endings, guitar tunints, clefs, key signatures, time signatures, notes, rests, accidentals, drum tabs, piano grand staff, tied notes, grace notes, dead notes, ghost notes, markers, tempos, lyrics, chords, vibratos, dynamics, tap/slap/pop, fade-in, let-ring, palm-mute, string bends, whammy bar, tremolo picking, strokes, slides, trills, pick strokes, tuplets, fingering, triplet feels,... * adapt to your responsive design by dynamic resizing -* play the music sheet via HTML5 Web Audio API (only if browser supports it) +* play the music sheet via built-in Midi+SoundFont2 Synthesizer (output depends on platform: HTML5 Web Audio, NAudio, Android AudioTrack) + +# Officially Supported Platforms + + Platform | Support | Availability | +----------|---------|-------| +Browsers using `script` includes (UMD) | Full experience including low level APIs, Background Workers, Audio Playback, SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. | 1.0-latest +Node.js using `require` (UMD) | Access to all low level APIs and SVG rendering | 1.0-latest +.net standard 2.0 | Access to all low level APIs and multiple render engines (SVG, GDI+, SkiaSharp) | 1.0-latest +.netcoreapp3.1 (WPF) | Full experience including low level APIs, Background Workers, Audio Playback (through NAudio), SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. | 1.0-1.2.2 +.netcoreapp3.1 (WinForms) | Full experience including low level APIs, Background Workers, Audio Playback (through NAudio), SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. Reduced UI level integration related to transparency and animations. | 1.0-1.2.2 +Browsers using ES6 Modules (ESM) | Full experience including low level APIs, Background Workers, Audio Playback, SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. | 1.3 (pre-release :warning:) +Node.js using `import` (ESM) | Access to all low level APIs and SVG rendering | 1.3 (pre-release :warning:) +.net6.0-windows (WPF) | Full experience including low level APIs, Background Workers, Audio Playback (through NAudio), SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. | 1.3 (pre-release :warning:) +.net6.0-windows (WinForms) | Full experience including low level APIs, Background Workers, Audio Playback (through NAudio), SVG and HTML5 rendering. UI level integration for user interaction and automatic resizing. Reduced UI level integration related to transparency and animations. | 1.3 (pre-release :warning:) +Android (Kotlin) | Full experience including low level APIs, Background Workers, Audio Playback, Android Canvas and SVG rendering. UI level integration for user interaction and automatic resizing. Reduced UI level integration related to transparency and animations. | 1.3 (pre-release :warning:) # Thanks to... -... the guys of BrowserStack for a free plan. This allows me to test alphaTab on all browsers on all operating systems. Only with this I can ensure that alphaTab is shown to all your visitors as expected. +... our friends of BrowserStack for a free plan. This allows me to test alphaTab on all browsers on all operating systems. Only with this I can ensure that alphaTab is shown to all your visitors as expected.

+... our friends at JetBrains for a Open Source License of their products. This allows me to develop all the flavors of alphaTab with the latest and greatest coding and debugging assistance. + +

+
+Copyright © 2000-2022 JetBrains s.r.o. JetBrains and the JetBrains logo are registered trademarks of JetBrains s.r.o. +

+ ... to [Bernhard Schelling](https://github.com/schellingb/TinySoundFont) the author of TinySoundFont and [Steve Folta](https://github.com/stevefolta/SFZero) the author of SFZero for providing the core of the synthesis engine. -... to all you people using alphaTab providing new feature ideas and and bug reports. +... to all you people using alphaTab providing new feature ideas and bug reports. diff --git a/font/bravura/FONTLOG.txt b/font/bravura/Bravura-FONTLOG.txt similarity index 100% rename from font/bravura/FONTLOG.txt rename to font/bravura/Bravura-FONTLOG.txt diff --git a/font/bravura/OFL-FAQ.txt b/font/bravura/Bravura-OFL-FAQ.txt similarity index 100% rename from font/bravura/OFL-FAQ.txt rename to font/bravura/Bravura-OFL-FAQ.txt diff --git a/font/bravura/OFL.txt b/font/bravura/Bravura-OFL.txt similarity index 100% rename from font/bravura/OFL.txt rename to font/bravura/Bravura-OFL.txt diff --git a/font/ptserif/PTSerif-Bold.ttf b/font/ptserif/PTSerif-Bold.ttf new file mode 100644 index 000000000..b95573250 Binary files /dev/null and b/font/ptserif/PTSerif-Bold.ttf differ diff --git a/font/ptserif/PTSerif-BoldItalic.ttf b/font/ptserif/PTSerif-BoldItalic.ttf new file mode 100644 index 000000000..e933f845e Binary files /dev/null and b/font/ptserif/PTSerif-BoldItalic.ttf differ diff --git a/font/ptserif/PTSerif-Italic.ttf b/font/ptserif/PTSerif-Italic.ttf new file mode 100644 index 000000000..e53ac86f5 Binary files /dev/null and b/font/ptserif/PTSerif-Italic.ttf differ diff --git a/font/ptserif/PTSerif-OFL.txt b/font/ptserif/PTSerif-OFL.txt new file mode 100644 index 000000000..3f70bfe03 --- /dev/null +++ b/font/ptserif/PTSerif-OFL.txt @@ -0,0 +1,94 @@ +Copyright (c) 2010, ParaType Ltd. (http://www.paratype.com/public), +with Reserved Font Names "PT Sans", "PT Serif" and "ParaType". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/font/ptserif/PTSerif-Regular.ttf b/font/ptserif/PTSerif-Regular.ttf new file mode 100644 index 000000000..24af47855 Binary files /dev/null and b/font/ptserif/PTSerif-Regular.ttf differ diff --git a/font/roboto/LICENSE.txt b/font/roboto/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/font/roboto/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/font/roboto/Roboto-Bold.ttf b/font/roboto/Roboto-Bold.ttf new file mode 100644 index 000000000..d998cf5b4 Binary files /dev/null and b/font/roboto/Roboto-Bold.ttf differ diff --git a/font/roboto/Roboto-BoldItalic.ttf b/font/roboto/Roboto-BoldItalic.ttf new file mode 100644 index 000000000..b4e221039 Binary files /dev/null and b/font/roboto/Roboto-BoldItalic.ttf differ diff --git a/font/roboto/Roboto-Italic.ttf b/font/roboto/Roboto-Italic.ttf new file mode 100644 index 000000000..5b390ff95 Binary files /dev/null and b/font/roboto/Roboto-Italic.ttf differ diff --git a/font/roboto/Roboto-Regular.ttf b/font/roboto/Roboto-Regular.ttf new file mode 100644 index 000000000..2b6392ffe Binary files /dev/null and b/font/roboto/Roboto-Regular.ttf differ diff --git a/karma.conf.js b/karma.conf.js index dc0cd27c7..f2d5605b9 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -47,7 +47,8 @@ module.exports = function (config) { clearContext: false, jasmine: { random: false, - stopSpecOnExpectationFailure: false + stopSpecOnExpectationFailure: false.valueOf, + timeoutInterval: 30000 } }, @@ -145,6 +146,7 @@ module.exports = function (config) { output: { format: 'iife', name: 'alphaTab', + file: 'dist/lib.test/test.bundle.js', sourcemap: false } } diff --git a/package-lock.json b/package-lock.json index fb0ace807..89fefea38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,4328 +1,6128 @@ { - "name": "@coderline/alphatab", - "version": "1.2.2", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" - } - }, - "@rollup/plugin-commonjs": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.0.0.tgz", - "integrity": "sha512-/omBIJG1nHQc+bgkYDuLpb/V08QyutP9amOrJRUSlYJZP+b/68gM//D8sxJe3Yry2QnYIr3QjR3x4AlxJEN3GA==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "dependencies": { - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - } - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } - } - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/jasmine": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.2.tgz", - "integrity": "sha512-AzfesNFLvOs6Q1mHzIsVJXSeUnqVh4ZHG8ngygKJfbkcSLwzrBVm/LKa+mR8KrOfnWtUL47112gde1MC0IXqpQ==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "13.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", - "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", - "dev": true - }, - "@types/resize-observer-browser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.5.tgz", - "integrity": "sha512-8k/67Z95Goa6Lznuykxkfhq9YU3l1Qe6LNZmwde1u7802a3x8v44oq0j91DICclxatTr0rNnhXx7+VTIetSrSQ==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "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" - } - }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=", - "dev": true - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", - "dev": true - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "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" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "dev": true, - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "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" - } - }, - "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "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 - }, - "colorette": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", - "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "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 - }, - "commenting": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/commenting/-/commenting-1.1.0.tgz", - "integrity": "sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "name": "@coderline/alphatab", + "version": "1.2.3", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@coderline/alphatab", + "version": "1.2.3", + "license": "MPL-2.0", + "devDependencies": { + "@rollup/plugin-commonjs": "^23.0.0", + "@types/jasmine": "^4.0.3", + "concurrently": "^7.2.1", + "cors": "^2.8.5", + "fs-extra": "^10.1.0", + "karma": "^6.3.20", + "karma-chrome-launcher": "^3.1.1", + "karma-express-http-server": "0.0.1", + "karma-jasmine": "^5.0.1", + "karma-jasmine-html-reporter": "^2.0.0", + "karma-rollup-preprocessor": "^7.0.8", + "karma-spec-reporter": "0.0.34", + "multer": "^1.4.5-lts.1", + "rimraf": "^3.0.2", + "rollup": "^2.75.1", + "rollup-plugin-copy": "^3.4.0", + "rollup-plugin-dts": "^4.2.2", + "rollup-plugin-license": "^2.8.0", + "rollup-plugin-serve": "^2.0.0", + "rollup-plugin-terser": "^7.0.2", + "terser": "^5.13.1", + "ts-node": "^10.8.0", + "tslint": "^6.1.3", + "tslint-config-prettier": "^1.18.0", + "tslint-config-standard": "^9.0.0", + "typescript": "^4.8.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^4.2.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/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/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "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/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/fs-extra": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz", + "integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.0.tgz", + "integrity": "sha512-u1jWakf8CWvLfSEZyxmzkgBzOEvXH/szpT0e6G8BTkx5Eu0BhDn7sbc5dz0JBN/6Wwm9rBe+JAsk9tJRyH9ZkA==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", + "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "dev": true + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/array-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/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "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/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commenting": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commenting/-/commenting-1.1.0.tgz", + "integrity": "sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/concurrently": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.4.0.tgz", + "integrity": "sha512-M6AfrueDt/GEna/Vg9BqQ+93yuvzkSKmoTixnwEJkH0LlcGrRC2eCmjeG1tLLHIYfpYJABokqSGyMcXjm96AFA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/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/concurrently/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/concurrently/node_modules/chalk/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/concurrently/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/concurrently/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/concurrently/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/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/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/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "node_modules/date-fns": { + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz", + "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==", + "dev": true, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "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/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "dependencies": { + "esutils": "^1.1.6", + "isarray": "0.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/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/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/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/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/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/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==", + "dev": true + }, + "node_modules/esutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "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/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "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.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "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/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "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": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/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/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/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "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/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/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/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/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/jasmine-core": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", + "integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", + "dev": true + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "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/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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/karma": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", + "integrity": "sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-express-http-server": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/karma-express-http-server/-/karma-express-http-server-0.0.1.tgz", + "integrity": "sha1-zLbLSRJoEMS28RvP9aOappuqWBc=", + "dev": true, + "dependencies": { + "express": ">=4.4.2" + }, + "peerDependencies": { + "karma": ">=0.11.14" + } + }, + "node_modules/karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "dependencies": { + "jasmine-core": "^4.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "karma": "^6.0.0" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.0.0.tgz", + "integrity": "sha512-SB8HNNiazAHXM1vGEzf8/tSyEhkfxuDdhYdPBX2Mwgzt0OuF2gicApQ+uvXLID/gXyJQgvrM9+1/2SxZFUUDIA==", + "dev": true, + "peerDependencies": { + "jasmine-core": "^4.0.0", + "karma": "^6.0.0", + "karma-jasmine": "^5.0.0" + } + }, + "node_modules/karma-rollup-preprocessor": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz", + "integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==", + "dev": true, + "dependencies": { + "chokidar": "^3.3.1", + "debounce": "^1.2.0" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": ">= 1.0.0" + } + }, + "node_modules/karma-spec-reporter": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.34.tgz", + "integrity": "sha512-l5H/Nh9q4g2Ysx2CDU2m+NIPyLQpCVbk9c4V02BTZHw3NM6RO1dq3eRpKXCSSdPt4RGfhHk8jDt3XYkGp+5PWg==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + }, + "peerDependencies": { + "karma": ">=0.9" + } + }, + "node_modules/karma/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/karma/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/log4js/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/magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" + } + }, + "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/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/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-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dev": true, + "dependencies": { + "mime-db": "1.43.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "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/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true, + "engines": { + "node": "*" + } + }, + "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/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dev": true, + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "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/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/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/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/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/package-name-regex": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/package-name-regex/-/package-name-regex-2.0.6.tgz", + "integrity": "sha512-gFL35q7kbE/zBaPA3UKhp2vSzcPYx2ecbYuwv1ucE9Il6IIgBDweBlH8D68UFGZic2MkllKa2KHCfC1IQBQUYA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/dword-design" + } + }, + "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/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-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/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "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==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "concurrently": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", - "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - } - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "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 - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "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-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "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=", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "date-fns": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", - "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==", - "dev": true - }, - "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", - "dev": true - }, - "debounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", - "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==", - "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" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", - "dev": true, - "requires": { - "esutils": "^1.1.6", - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-copy": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", + "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.2.3.tgz", + "integrity": "sha512-jlcpItqM2efqfIiKzDB/IKOS9E9fDvbkJSGw5GtK/PqPGS9eC3R3JKyw2VvpTktZA+TNgJRMu1NTv244aTUzzQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.26.6" + }, + "engines": { + "node": ">=v12.22.12" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.18.6" + }, + "peerDependencies": { + "rollup": "^2.55", + "typescript": "^4.1" + } + }, + "node_modules/rollup-plugin-license": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-license/-/rollup-plugin-license-2.8.1.tgz", + "integrity": "sha512-VYd9pzaNL7NN6xQp93XiiCV2UoduXgSmTcz6rl9bHPdiifT6yH3Zw/omEr73Rq8TIyN4nqJACBbKIT/2eE66wg==", + "dev": true, + "dependencies": { + "commenting": "~1.1.0", + "glob": "~7.2.0", + "lodash": "~4.17.21", + "magic-string": "~0.26.2", + "mkdirp": "~1.0.4", + "moment": "~2.29.3", + "package-name-regex": "~2.0.6", + "spdx-expression-validate": "~2.0.0", + "spdx-satisfies": "~5.0.1" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "rollup": "^1.0.0 || ^2.0.0" + } + }, + "node_modules/rollup-plugin-license/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/rollup-plugin-license/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup-plugin-serve": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-serve/-/rollup-plugin-serve-2.0.1.tgz", + "integrity": "sha512-/9lnzylTMwbXNQUwWAO0DIxW145wl+rmikwFXgujLJ5N9bRfWcjP+qd1XM5wxSiw8ZlBAlFy/n2zRvzcG21bBw==", + "dev": true, + "dependencies": { + "mime": ">=2.4.6", + "opener": "1" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/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/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/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "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.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "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/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/socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/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/socket.io/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/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/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, + "node_modules/spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.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-expression-validate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", + "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^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/spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "node_modules/spdx-satisfies": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-5.0.1.tgz", + "integrity": "sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==", + "dev": true, + "dependencies": { + "spdx-compare": "^1.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/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/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/streamroller/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/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "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/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/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/terser": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", + "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/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.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true, + "bin": { + "tslint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/tslint-config-standard": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/tslint-config-standard/-/tslint-config-standard-9.0.0.tgz", + "integrity": "sha512-CAw9J743RnPMemQV/XQ4YyNreC+A1NItACfkm+cBedrOkz6CQfwlnbKn8anUXBfoa4Zo4tjAhblRbsMNcSLfSw==", + "deprecated": "TSLint is deprecated, please move to ESLint: https://github.com/blakeembrey/tslint-config-standard/issues/61", + "dev": true, + "dependencies": { + "tslint-eslint-rules": "^5.3.1" + } + }, + "node_modules/tslint-config-standard/node_modules/tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", + "dev": true + }, + "node_modules/tslint-config-standard/node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/tslint-config-standard/node_modules/tslint-eslint-rules": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz", + "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==", + "dev": true, + "dependencies": { + "doctrine": "0.7.2", + "tslib": "1.9.0", + "tsutils": "^3.0.0" + }, + "peerDependencies": { + "tslint": "^5.0.0", + "typescript": "^2.2.0 || ^3.0.0" + } + }, + "node_modules/tslint-config-standard/node_modules/tslint-eslint-rules/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/tslint-config-standard/node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/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/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "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/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.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/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/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "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/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/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/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } } - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "engine.io": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", - "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "0.3.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" - }, - "dependencies": { + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@rollup/plugin-commonjs": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^4.2.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" + }, + "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.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "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.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/fs-extra": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz", + "integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.0.tgz", + "integrity": "sha512-u1jWakf8CWvLfSEZyxmzkgBzOEvXH/szpT0e6G8BTkx5Eu0BhDn7sbc5dz0JBN/6Wwm9rBe+JAsk9tJRyH9ZkA==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", + "dev": true + }, + "@types/node": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", + "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-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 + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "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" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-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 + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "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 + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "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" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "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" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "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" + } + }, + "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 + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "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 + }, + "commenting": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commenting/-/commenting-1.1.0.tgz", + "integrity": "sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "concurrently": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.4.0.tgz", + "integrity": "sha512-M6AfrueDt/GEna/Vg9BqQ+93yuvzkSKmoTixnwEJkH0LlcGrRC2eCmjeG1tLLHIYfpYJABokqSGyMcXjm96AFA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "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": "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" + } + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true + } + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "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 + }, + "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 + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "date-fns": { + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz", + "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==", + "dev": true + }, + "date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true + }, + "debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "requires": { + "esutils": "^1.1.6", + "isarray": "0.0.1" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "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 + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "requires": { + "@socket.io/base64-arraybuffer": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "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 + }, + "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==", + "dev": true + }, + "esutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "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.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "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==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.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" + } + }, + "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" + } + }, + "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.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "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": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "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 + }, + "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 + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "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" + } + }, + "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" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "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-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true + }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jasmine-core": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", + "integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "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" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "karma": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", + "integrity": "sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "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" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-express-http-server": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/karma-express-http-server/-/karma-express-http-server-0.0.1.tgz", + "integrity": "sha1-zLbLSRJoEMS28RvP9aOappuqWBc=", + "dev": true, + "requires": { + "express": ">=4.4.2" + } + }, + "karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "requires": { + "jasmine-core": "^4.1.0" + } + }, + "karma-jasmine-html-reporter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.0.0.tgz", + "integrity": "sha512-SB8HNNiazAHXM1vGEzf8/tSyEhkfxuDdhYdPBX2Mwgzt0OuF2gicApQ+uvXLID/gXyJQgvrM9+1/2SxZFUUDIA==", + "dev": true, + "requires": {} + }, + "karma-rollup-preprocessor": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz", + "integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==", + "dev": true, + "requires": { + "chokidar": "^3.3.1", + "debounce": "^1.2.0" + } + }, + "karma-spec-reporter": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.34.tgz", + "integrity": "sha512-l5H/Nh9q4g2Ysx2CDU2m+NIPyLQpCVbk9c4V02BTZHw3NM6RO1dq3eRpKXCSSdPt4RGfhHk8jDt3XYkGp+5PWg==", + "dev": true, + "requires": { + "colors": "1.4.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "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 + }, + "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 + }, + "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-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dev": true, + "requires": { + "mime-db": "1.43.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "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 - } - } - }, - "engine.io-client": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", - "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", - "dev": true, - "requires": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", - "dev": true - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", - "dev": true + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dev": true, + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "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" - } - }, - "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 - }, - "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 - }, - "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==", - "dev": true - }, - "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "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.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "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 + }, + "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 + }, + "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" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, + "package-name-regex": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/package-name-regex/-/package-name-regex-2.0.6.tgz", + "integrity": "sha512-gFL35q7kbE/zBaPA3UKhp2vSzcPYx2ecbYuwv1ucE9Il6IIgBDweBlH8D68UFGZic2MkllKa2KHCfC1IQBQUYA==", + "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 + }, + "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-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 + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "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==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.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 + }, + "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.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "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" + } + }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-copy": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", + "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", + "dev": true, + "requires": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "rollup-plugin-dts": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.2.3.tgz", + "integrity": "sha512-jlcpItqM2efqfIiKzDB/IKOS9E9fDvbkJSGw5GtK/PqPGS9eC3R3JKyw2VvpTktZA+TNgJRMu1NTv244aTUzzQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "magic-string": "^0.26.6" + } + }, + "rollup-plugin-license": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-license/-/rollup-plugin-license-2.8.1.tgz", + "integrity": "sha512-VYd9pzaNL7NN6xQp93XiiCV2UoduXgSmTcz6rl9bHPdiifT6yH3Zw/omEr73Rq8TIyN4nqJACBbKIT/2eE66wg==", + "dev": true, + "requires": { + "commenting": "~1.1.0", + "glob": "~7.2.0", + "lodash": "~4.17.21", + "magic-string": "~0.26.2", + "mkdirp": "~1.0.4", + "moment": "~2.29.3", + "package-name-regex": "~2.0.6", + "spdx-expression-validate": "~2.0.0", + "spdx-satisfies": "~5.0.1" + }, + "dependencies": { + "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" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "rollup-plugin-serve": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-serve/-/rollup-plugin-serve-2.0.1.tgz", + "integrity": "sha512-/9lnzylTMwbXNQUwWAO0DIxW145wl+rmikwFXgujLJ5N9bRfWcjP+qd1XM5wxSiw8ZlBAlFy/n2zRvzcG21bBw==", + "dev": true, + "requires": { + "mime": ">=2.4.6", + "opener": "1" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "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==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } + "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 }, - "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" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fast-glob": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", - "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "fastq": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz", - "integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==", - "dev": true, - "requires": { - "reusify": "^1.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" - } - }, - "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" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "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.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs-extra": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", - "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - }, - "dependencies": { - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "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.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "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-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "git-branch": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/git-branch/-/git-branch-2.0.1.tgz", - "integrity": "sha512-jMCT1kjXvsUdZKQd2p8E1uZhKsIuR1pnHgcDYQpQiXBtzE9cmYGvOcCSGqqi58x0B9CPS0lUSu/yti866est8g==", - "dev": true, - "requires": { - "findup-sync": "^2.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "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" - } - }, - "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" - } - }, - "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "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-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "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-plain-object": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", - "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", - "dev": true, - "requires": { - "isobject": "^4.0.0" - } - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "isbinaryfile": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", - "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", - "dev": true - }, - "jasmine-core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", - "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", - "dev": true - }, - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "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 + "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 }, - "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" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "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 - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "karma": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.3.tgz", - "integrity": "sha512-tHdyFADhVVPBorIKCX8A37iLHxc6RBRphkSoQ+MLKdAtFn1k97tD8WUGi1KlEtDZKL3hui0qhsY9HXUfSNDYPQ==", - "dev": true, - "requires": { - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.4.2", - "colors": "^1.4.0", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.6", - "graceful-fs": "^4.2.4", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.6", - "lodash": "^4.17.19", - "log4js": "^6.2.1", - "mime": "^2.4.5", - "minimatch": "^3.0.4", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^2.3.0", - "source-map": "^0.6.1", - "tmp": "0.2.1", - "ua-parser-js": "0.7.22", - "yargs": "^15.3.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } + "socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } }, - "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } + "socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } }, - "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" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, - "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 + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true }, - "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 - }, - "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" - } + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "requires": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.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-expression-validate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", + "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", + "dev": true, + "requires": { + "spdx-expression-parse": "^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 + }, + "spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "spdx-satisfies": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-5.0.1.tgz", + "integrity": "sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==", + "dev": true, + "requires": { + "spdx-compare": "^1.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "terser": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", + "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + } + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "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" + } }, - "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 - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-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" - } - }, - "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 + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true }, - "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" - } + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + } }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } + "tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", - "dev": true, - "requires": { - "which": "^1.2.1" - } - }, - "karma-express-http-server": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/karma-express-http-server/-/karma-express-http-server-0.0.1.tgz", - "integrity": "sha1-zLbLSRJoEMS28RvP9aOappuqWBc=", - "dev": true, - "requires": { - "express": ">=4.4.2" - } - }, - "karma-jasmine": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", - "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", - "dev": true, - "requires": { - "jasmine-core": "^3.6.0" - } - }, - "karma-jasmine-html-reporter": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.4.tgz", - "integrity": "sha512-PtilRLno5O6wH3lDihRnz0Ba8oSn0YUJqKjjux1peoYGwo0AQqrWRbdWk/RLzcGlb+onTyXAnHl6M+Hu3UxG/Q==", - "dev": true - }, - "karma-rollup-preprocessor": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.5.tgz", - "integrity": "sha512-VhZI81l8LZBvBrSf4xaojsbur7bcycsSlxXkYaTOjV6DQwx1gtAM0CQVdue7LuIbXB1AohYIg0S5at+dqDtMxQ==", - "dev": true, - "requires": { - "chokidar": "^3.3.1", - "debounce": "^1.2.0" - } - }, - "karma-spec-reporter": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.32.tgz", - "integrity": "sha1-LpxyB+pyZ3EmAln4K+y1QyCeRAo=", - "dev": true, - "requires": { - "colors": "^1.1.2" - } - }, - "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 - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", - "dev": true, - "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } + "tslint-config-standard": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/tslint-config-standard/-/tslint-config-standard-9.0.0.tgz", + "integrity": "sha512-CAw9J743RnPMemQV/XQ4YyNreC+A1NItACfkm+cBedrOkz6CQfwlnbKn8anUXBfoa4Zo4tjAhblRbsMNcSLfSw==", + "dev": true, + "requires": { + "tslint-eslint-rules": "^5.3.1" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", + "dev": true + }, + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "peer": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + } + }, + "tslint-eslint-rules": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz", + "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==", + "dev": true, + "requires": { + "doctrine": "0.7.2", + "tslib": "1.9.0", + "tsutils": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "peer": 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 - } - } - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "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 - }, - "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-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", - "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.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "dev": true - }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "dev": true, - "requires": { - "mime-db": "1.43.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } }, - "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" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multer": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", - "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", - "dev": true, - "requires": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.1", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - } - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "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" - } - }, - "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 - }, - "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-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "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" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "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": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-name-regex": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/package-name-regex/-/package-name-regex-1.0.8.tgz", - "integrity": "sha512-g3vB2J62dLqf4m50VM4tJUC4sixw3JB+Igd0cF3P/gJhAvmvsmFEV2eWZTeLbwfkKEWTf3+gwQ2C6JFFRxWHEQ==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "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-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "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 - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - } - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", - "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.7" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "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.1.4", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", - "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" - } - }, - "rollup": { - "version": "2.35.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.35.1.tgz", - "integrity": "sha512-q5KxEyWpprAIcainhVy6HfRttD9kutQpHbeqDTWnqAFNJotiojetK6uqmcydNMymBEtC4I8bCYR+J3mTMqeaUA==", - "dev": true, - "requires": { - "fsevents": "~2.1.2" - } - }, - "rollup-plugin-copy": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.3.0.tgz", - "integrity": "sha512-euDjCUSBXZa06nqnwCNADbkAcYDfzwowfZQkto9K/TFhiH+QG7I4PUsEMwM9tDgomGWJc//z7KLW8t+tZwxADA==", - "dev": true, - "requires": { - "@types/fs-extra": "^8.0.1", - "colorette": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "10.0.1", - "is-plain-object": "^3.0.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } - } - }, - "rollup-plugin-dts": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-2.0.1.tgz", - "integrity": "sha512-y38NSXIY37YExCumbGBTL5dXg7pL7XD+Kbe98iEHWFN9yiKJf7t4kKBOkml5ylUDjQIXBnNClGDeRktc1T5dmA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "magic-string": "^0.25.7" - } - }, - "rollup-plugin-license": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-license/-/rollup-plugin-license-2.2.0.tgz", - "integrity": "sha512-xXb1vviEwlJMX+VGUSsglcMA/Rh9d2QzEm94awy4FlnsPqGrXoTYYGOR3UXR6gYIxiJFkr7qmkKF/NXfre/y8g==", - "dev": true, - "requires": { - "commenting": "1.1.0", - "glob": "7.1.6", - "lodash": "4.17.19", - "magic-string": "0.25.7", - "mkdirp": "1.0.4", - "moment": "2.27.0", - "package-name-regex": "1.0.8", - "spdx-expression-validate": "2.0.0", - "spdx-satisfies": "5.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "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" + } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "rollup-plugin-serve": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-serve/-/rollup-plugin-serve-1.1.0.tgz", - "integrity": "sha512-pYkSsuA0/psKqhhictkJw1c2klya5b+LlCvipWqI9OE1aG2M97mRumZCbBlry5CMEOzYBBgSDgd1694sNbmyIw==", - "dev": true, - "requires": { - "mime": ">=2.4.6", - "opener": "1" - } - }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true + "typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true }, - "terser": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.8.tgz", - "integrity": "sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - } - } - } - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", - "dev": true, - "requires": { - "tslib": "^1.9.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==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "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.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, - "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" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", - "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", - "dev": true, - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.4.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", - "socket.io-parser": "~3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "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 - } - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", - "dev": true - }, - "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true }, - "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 + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, - "socket.io-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", - "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", - "dev": true, - "requires": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "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 + } } - } - } - } - }, - "socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", - "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } }, - "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 - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", - "dev": true - }, - "spdx-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", - "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", - "dev": true, - "requires": { - "array-find-index": "^1.0.2", - "spdx-expression-parse": "^3.0.0", - "spdx-ranges": "^2.0.0" - } - }, - "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.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-expression-validate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", - "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "spdx-ranges": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", - "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", - "dev": true - }, - "spdx-satisfies": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-5.0.0.tgz", - "integrity": "sha512-/hGhwh20BeGmkA+P/lm06RvXD94JduwNxtx/oX3B5ClPt1/u/m5MCaDNo1tV3Y9laLkQr/NRde63b9lLMhlNfw==", - "dev": true, - "requires": { - "spdx-compare": "^1.0.0", - "spdx-expression-parse": "^3.0.0", - "spdx-ranges": "^2.0.0" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "requires": {} }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "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 - } - } - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "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" - } - }, - "terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - } - }, - "tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", - "dev": true - }, - "tslint-config-standard": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/tslint-config-standard/-/tslint-config-standard-9.0.0.tgz", - "integrity": "sha512-CAw9J743RnPMemQV/XQ4YyNreC+A1NItACfkm+cBedrOkz6CQfwlnbKn8anUXBfoa4Zo4tjAhblRbsMNcSLfSw==", - "dev": true, - "requires": { - "tslint-eslint-rules": "^5.3.1" - } - }, - "tslint-eslint-rules": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz", - "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==", - "dev": true, - "requires": { - "doctrine": "0.7.2", - "tslib": "1.9.0", - "tsutils": "^3.0.0" - }, - "dependencies": { - "tslib": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", - "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", - "dev": true + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "ttypescript": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/ttypescript/-/ttypescript-1.5.12.tgz", - "integrity": "sha512-1ojRyJvpnmgN9kIHmUnQPlEV1gq+VVsxVYjk/NfvMlHSmYxjK5hEvOOU2MQASrbekTUiUM7pR/nXeCc8bzvMOQ==", - "dev": true, - "requires": { - "resolve": ">=1.9.0" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", - "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.22", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", - "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "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 + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "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 - }, - "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 - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "ws": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", - "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true } - } } diff --git a/package.json b/package.json index a52eec40b..ba7f10d5d 100644 --- a/package.json +++ b/package.json @@ -1,84 +1,91 @@ { - "name": "@coderline/alphatab", - "version": "1.2.2", - "description": "alphaTab is a music notation and guitar tablature rendering library", - "keywords": [ - "guitar", - "music-notation", - "music-sheet", - "html5", - "svg", - "guitar-tablature" - ], - "homepage": "https://alphatab.net", - "bugs": { - "url": "https://github.com/coderline/alphaTab/issues" - }, - "author": "Daniel Kuschny", - "license": "MPL-2.0", - "repository": { - "type": "git", - "url": "https://github.com/coderline/alphaTab" - }, - "main": "dist/alphaTab.js", - "typings": "dist/alphaTab.d.ts", - "engines": { - "node": ">=6.0.0" - }, - "scripts": { - "clean": "rimraf dist", - "lint": "tslint --project tsconfig.build.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'", - "build": "npm run generate-typescript && tsc --project tsconfig.build.json && rollup -c rollup.config.js", - "build-ci": "npm run clean && npm run build && npm pack", - "start": "node scripts/setup-playground.js && npm run build && concurrently --kill-others \"tsc --project tsconfig.build.json --watch\" \"rollup -c rollup.config.js -w\"", - "test": "npm run generate-typescript && tsc --project tsconfig.json && concurrently --kill-others \"tsc --project tsconfig.json -w\" \"karma start karma.conf.js --browsers Chrome --no-single-run --reporters spec,kjhtml\"", - "test-ci": "npm run generate-typescript && tsc --project tsconfig.json && karma start karma.conf.js --browsers ChromeHeadless --single-run --reporters spec", - "generate-typescript": "rimraf src/generated && ts-node --project tsconfig.build-csharp.json src.compiler/typescript/AlphaTabGenerator.ts --project tsconfig.build-csharp.json", - "generate-csharp": "npm run generate-typescript && ts-node --project tsconfig.build-csharp.json src.compiler/csharp/CSharpTranspiler.ts --project tsconfig.build-csharp.json", - "build-csharp": "npm run generate-csharp && cd src.csharp && dotnet build -c Release", - "build-csharp-ci": "npm run clean && npm run generate-csharp && cd src.csharp && dotnet build -c Release", - "test-csharp": "cd src.csharp && dotnet test", - "test-csharp-ci": "cd src.csharp && dotnet test" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^17.0.0", - "@types/jasmine": "^3.6.2", - "@types/resize-observer-browser": "^0.1.5", - "concurrently": "^5.3.0", - "cors": "^2.8.5", - "fs-extra": "^9.0.1", - "git-branch": "^2.0.1", - "karma": "^5.2.3", - "karma-chrome-launcher": "^3.1.0", - "karma-express-http-server": "0.0.1", - "karma-jasmine": "^4.0.1", - "karma-jasmine-html-reporter": "^1.5.4", - "karma-rollup-preprocessor": "^7.0.5", - "karma-spec-reporter": "0.0.32", - "lodash": "^4.17.20", - "multer": "^1.4.2", - "rimraf": "^3.0.2", - "rollup": "^2.35.1", - "rollup-plugin-copy": "^3.3.0", - "rollup-plugin-dts": "^2.0.1", - "rollup-plugin-license": "^2.2.0", - "rollup-plugin-serve": "^1.1.0", - "rollup-plugin-terser": "^7.0.2", - "terser": "^5.5.1", - "ts-node": "^9.1.1", - "tslint": "^6.1.3", - "tslint-config-prettier": "^1.15.0", - "tslint-config-standard": "^9.0.0", - "ttypescript": "^1.5.12", - "typescript": "^4.1.3" - }, - "files": [ - "/dist/alphaTab.js", - "/dist/alphaTab.min.js", - "/dist/alphaTab.d.ts", - "/dist/font/Bravura.*", - "/dist/font/*.txt", - "/dist/soundfont/*", - "LICENSE.header" - ] + "name": "@coderline/alphatab", + "version": "1.2.3", + "description": "alphaTab is a music notation and guitar tablature rendering library", + "keywords": [ + "guitar", + "music-notation", + "music-sheet", + "html5", + "svg", + "guitar-tablature" + ], + "homepage": "https://alphatab.net", + "bugs": { + "url": "https://github.com/coderline/alphaTab/issues" + }, + "author": "Daniel Kuschny", + "license": "MPL-2.0", + "repository": { + "type": "git", + "url": "https://github.com/coderline/alphaTab" + }, + "main": "dist/alphaTab.js", + "module": "dist/alphaTab.mjs", + "typings": "dist/alphaTab.d.ts", + "exports": { + ".": { + "import": "./dist/alphaTab.mjs", + "require": "./dist/alphaTab.js" + }, + "./soundfont/*": "./dist/soundfont/*", + "./font/*": "./dist/font/*" + }, + "engines": { + "node": ">=6.0.0" + }, + "scripts": { + "clean": "rimraf dist", + "lint": "tslint --project tsconfig.build.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'", + "generate-typescript": "rimraf src/generated && ts-node --project tsconfig.build-csharp.json src.compiler/typescript/AlphaTabGenerator.ts --project tsconfig.build-csharp.json", + "generate-csharp": "npm run generate-typescript && ts-node --project tsconfig.build-csharp.json src.compiler/csharp/CSharpTranspiler.ts --project tsconfig.build-csharp.json", + "build": "npm run generate-typescript && tsc --project tsconfig.build.json && rollup -c rollup.config.js", + "build-ci": "npm run clean && npm run build && npm pack", + "build-csharp": "npm run generate-csharp && cd src.csharp && dotnet build -c Release", + "build-csharp-ci": "npm run clean && npm run generate-csharp && cd src.csharp && dotnet build -c Release", + "start": "node scripts/setup-playground.js && npm run build && concurrently --kill-others \"tsc --project tsconfig.build.json --watch\" \"rollup -c rollup.config.js -w\"", + "test": "npm run generate-typescript && tsc --project tsconfig.json && concurrently --kill-others \"tsc --project tsconfig.json -w\" \"karma start karma.conf.js --browsers Chrome --no-single-run --reporters spec,kjhtml\"", + "test-ci": "npm run generate-typescript && tsc --project tsconfig.json && karma start karma.conf.js --browsers ChromeHeadless --single-run --reporters spec", + "test-csharp": "cd src.csharp && dotnet test -c Release", + "test-csharp-ci": "cd src.csharp && dotnet test -c Release" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^23.0.0", + "@types/jasmine": "^4.0.3", + "concurrently": "^7.2.1", + "cors": "^2.8.5", + "fs-extra": "^10.1.0", + "karma": "^6.3.20", + "karma-chrome-launcher": "^3.1.1", + "karma-express-http-server": "0.0.1", + "karma-jasmine": "^5.0.1", + "karma-jasmine-html-reporter": "^2.0.0", + "karma-rollup-preprocessor": "^7.0.8", + "karma-spec-reporter": "0.0.34", + "multer": "^1.4.5-lts.1", + "rimraf": "^3.0.2", + "rollup": "^2.75.1", + "rollup-plugin-copy": "^3.4.0", + "rollup-plugin-dts": "^4.2.2", + "rollup-plugin-license": "^2.8.0", + "rollup-plugin-serve": "^2.0.0", + "rollup-plugin-terser": "^7.0.2", + "terser": "^5.13.1", + "ts-node": "^10.8.0", + "tslint": "^6.1.3", + "tslint-config-prettier": "^1.18.0", + "tslint-config-standard": "^9.0.0", + "typescript": "^4.8.3" + }, + "files": [ + "/dist/alphaTab.js", + "/dist/alphaTab.mjs", + "/dist/alphaTab.min.js", + "/dist/alphaTab.min.mjs", + "/dist/alphaTab.d.ts", + "/dist/font/Bravura.*", + "/dist/font/*.txt", + "/dist/soundfont/*", + "LICENSE.header" + ] } diff --git a/rollup.config.js b/rollup.config.js index a6764678f..d19f507dc 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -2,9 +2,19 @@ const resolve = require('./rollup.resolve'); const terser = require('rollup-plugin-terser').terser; const dts = require('rollup-plugin-dts').default; const copy = require('rollup-plugin-copy'); -const branch = require('git-branch'); const license = require('rollup-plugin-license'); const serve = require('rollup-plugin-serve'); +const fs = require('fs'); + +function getGitBranch() { + const filepath = '.git/HEAD'; + if (!fs.existsSync(filepath)) { + throw new Error('.git/HEAD does not exist'); + } + const buf = fs.readFileSync(filepath); + const match = /ref: refs\/heads\/([^\n]+)/.exec(buf.toString()); + return match ? match[1] : ''; +} const commonOutput = { name: 'alphaTab', @@ -14,6 +24,12 @@ const commonOutput = { } }; +const importMetaPlugin = { + resolveImportMeta() { + return '{}'; // prevent import.meta to be empty in non ES outputs + } +}; + const isWatch = process.env.ROLLUP_WATCH; module.exports = [ @@ -22,14 +38,22 @@ module.exports = [ output: [ { file: 'dist/alphaTab.js', - name: 'alphaTab' + plugins: [importMetaPlugin] }, { file: 'dist/alphaTab.min.js', - name: 'alphaTab', + plugins: [terser(), importMetaPlugin] + }, + { + file: 'dist/alphaTab.mjs', + format: 'es' + }, + { + file: 'dist/alphaTab.min.mjs', + format: 'es', plugins: [terser()] } - ].map(o => ({ ...o, ...commonOutput })), + ].map(o => ({ ...commonOutput, ...o })), external: [], watch: { include: 'dist/lib/**', @@ -43,7 +67,7 @@ module.exports = [ }, data() { let buildNumber = process.env.GITHUB_RUN_NUMBER || 0; - let gitBranch = branch.sync(); + let gitBranch = getGitBranch(); return { branch: gitBranch, build: buildNumber @@ -64,12 +88,13 @@ module.exports = [ } }), - isWatch && serve({ - open: true, - openPage: '/playground/control.html', - contentBase: '', - port: 8080 - }) + isWatch && + serve({ + open: true, + openPage: '/playground/control.html', + contentBase: '', + port: 8080 + }) ] }, { diff --git a/rollup.resolve.js b/rollup.resolve.js index c470c9d64..740315ae5 100644 --- a/rollup.resolve.js +++ b/rollup.resolve.js @@ -1,4 +1,4 @@ -const join = require('path').join; +const path = require('path'); const glob = require('glob').sync; const fs = require('fs'); @@ -14,22 +14,29 @@ module.exports = function (options) { const extension = types ? '.d.ts' : '.js'; - if (importee.startsWith('**')) { + if (fs.existsSync(importee)) { + return importee; + } else if (importee.startsWith('**')) { return importee; } else { + const importerDir = path.dirname(importer); + let resolved = importee; + const match = Object.entries(mappings).filter(m => importee.startsWith(m[0])); - if (!match || match.length === 0) { - return null; + if (match && match.length > 0) { + if (match[0][1].endsWith(extension)) { + resolved = path.join(process.cwd(), match[0][1]); + } else { + resolved = path.join(process.cwd(), match[0][1], importee.substring(match[0][0].length)); + } + } else { + resolved = path.join(importerDir, importee); } - if (match[0][1].endsWith(extension)) { - return join(process.cwd(), match[0][1]); + if (fs.existsSync(path.join(resolved, 'index' + extension))) { + resolved = path.join(resolved, 'index'); } - let resolved = join(process.cwd(), match[0][1], importee.substring(match[0][0].length)); - if (fs.existsSync(join(resolved, 'index' + extension))) { - return join(resolved, 'index' + extension); - } return resolved + extension; } }, @@ -39,11 +46,7 @@ module.exports = function (options) { cwd: process.cwd() }); const source = files - .map( - (file, i) => - `import _${i} from ${JSON.stringify(join(process.cwd(), file))}; - export { _${i} };` - ) + .map((file, i) => `export * as _${i} from ${JSON.stringify(path.join(process.cwd(), file))};`) .join('\r\n'); return source; } diff --git a/src.compiler/AstPrinterBase.ts b/src.compiler/AstPrinterBase.ts new file mode 100644 index 000000000..0ae50fedb --- /dev/null +++ b/src.compiler/AstPrinterBase.ts @@ -0,0 +1,590 @@ +import * as cs from './csharp/CSharpAst'; +import * as ts from 'typescript'; +import * as path from 'path'; +import * as fs from 'fs'; +import CSharpEmitterContext from './csharp/CSharpEmitterContext'; + +export default abstract class AstPrinterBase { + protected _sourceFile: cs.SourceFile; + private _source = ''; + protected _context: CSharpEmitterContext; + protected _isStartOfLine: boolean = true; + protected _indent: number = 0; + + public diagnostics: ts.Diagnostic[] = []; + + public constructor(sourceFile: cs.SourceFile, context: CSharpEmitterContext) { + this._sourceFile = sourceFile; + this._context = context; + } + + public print() { + fs.mkdirSync(path.dirname(this._sourceFile.fileName), { recursive: true }); + try { + this._source = ''; + this.writeSourceFile(this._sourceFile); + } finally { + fs.writeFileSync(this._sourceFile.fileName, this._source); + } + } + + protected abstract writeSourceFile(sourceFile: cs.SourceFile); + + protected writeSemicolon() { + this.writeLine(';'); + } + + protected writeLine(txt?: string) { + this.writeIndent(); + if (txt) { + this.write(txt); + } + this.write(ts.sys.newLine); + this._isStartOfLine = true; + } + + protected write(txt: string) { + this.writeIndent(); + this._source += txt; + this._isStartOfLine = false; + } + + protected writeIndent() { + if (this._isStartOfLine && this._indent > 0) { + this._source += this._indent === 1 ? ' ' : ' '.repeat(this._indent); + this._isStartOfLine = false; + } + } + + protected beginBlock() { + this.writeLine('{'); + this._indent++; + } + + protected endBlock() { + this._indent--; + this.writeLine('}'); + } + + protected writeNamespaceMembers(members: cs.NamespaceMember[]) { + for (const declaration of members) { + this.writeMember(declaration); + } + } + + protected writeCommaSeparated(values: T[], write: (p: T) => void, newLine:boolean = false) { + values.forEach((v, i) => { + if (i > 0) { + this.write(', '); + if(newLine) { + this.writeLine(); + } + } + write(v); + }); + } + + protected abstract writeClassDeclaration(d: cs.ClassDeclaration); + protected abstract writeEnumDeclaration(d: cs.EnumDeclaration); + protected abstract writeInterfaceDeclaration(d: cs.InterfaceDeclaration); + protected abstract writeParameter(p: cs.ParameterDeclaration); + + protected writeParameters(parameters: cs.ParameterDeclaration[]) { + this.write('('); + this.writeCommaSeparated(parameters, p => this.writeParameter(p)); + this.write(')'); + } + + protected writeAttributes(d: cs.AttributedElement) { + if (d.attributes) { + d.attributes.forEach(a => this.writeAttribute(a)); + } + } + + protected abstract writeAttribute(a: cs.Attribute); + + protected abstract writeMethodDeclaration(d: cs.MethodDeclaration); + protected abstract writeFieldDeclarat1on(d: cs.FieldDeclaration); + protected abstract writePropertyDeclaration(d: cs.PropertyDeclaration); + protected abstract writeConstructorDeclaration(d: cs.ConstructorDeclaration); + + protected writeMember(member: cs.Node) { + if (member.skipEmit) { + return; + } + + switch (member.nodeType) { + case cs.SyntaxKind.FieldDeclaration: + this.writeFieldDeclarat1on(member as cs.FieldDeclaration); + break; + case cs.SyntaxKind.PropertyDeclaration: + this.writePropertyDeclaration(member as cs.PropertyDeclaration); + break; + case cs.SyntaxKind.ConstructorDeclaration: + this.writeConstructorDeclaration(member as cs.ConstructorDeclaration); + break; + case cs.SyntaxKind.MethodDeclaration: + this.writeMethodDeclaration(member as cs.MethodDeclaration); + break; + case cs.SyntaxKind.ClassDeclaration: + this.writeClassDeclaration(member as cs.ClassDeclaration); + break; + case cs.SyntaxKind.EnumDeclaration: + this.writeEnumDeclaration(member as cs.EnumDeclaration); + break; + case cs.SyntaxKind.InterfaceDeclaration: + this.writeInterfaceDeclaration(member as cs.InterfaceDeclaration); + break; + } + this.writeLine(); + } + + protected canBeConstant(d: cs.PropertyDeclaration): boolean { + return ( + d.isStatic && + !d.setAccessor && + cs.isPrimitiveTypeNode(d.type) && + !!d.initializer && + (!d.getAccessor || !d.getAccessor.body) + ); + } + + protected writePropertyAsField(d: cs.PropertyDeclaration) { + if ( + cs.isClassDeclaration(d.parent!) && + d.visibility === cs.Visibility.Private && + (!d.getAccessor || !d.getAccessor.body) + ) { + return true; + } + return this.canBeConstant(d); + } + + protected abstract writeType( + type: cs.TypeNode, + forNew?: boolean, + asNativeArray?: boolean, + forTypeConstraint?: boolean + ); + + protected abstract writePrefixUnaryExpression(expr: cs.PrefixUnaryExpression); + protected abstract writeBaseLiteralExpression(expr: cs.BaseLiteralExpression); + protected abstract writeAwaitExpression(expr: cs.AwaitExpression); + protected abstract writeBinaryExpression(expr: cs.BinaryExpression); + protected abstract writeConditionalExpression(expr: cs.ConditionalExpression); + protected abstract writeLambdaExpression(expr: cs.LambdaExpression); + protected abstract writeNumericLiteral(expr: cs.NumericLiteral); + protected abstract writeStringTemplateExpression(expr: cs.StringTemplateExpression); + protected abstract writeArrayCreationExpression(expr: cs.ArrayCreationExpression); + protected abstract writeTypeOfExpression(expr: cs.TypeOfExpression); + protected abstract writeMemberAccessExpression(expr: cs.MemberAccessExpression); + protected abstract writeElementAccessExpression(expr: cs.ElementAccessExpression); + protected abstract writeNewExpression(expr: cs.NewExpression); + protected abstract writeCastExpression(expr: cs.CastExpression); + protected abstract writeNonNullExpression(expr: cs.NonNullExpression); + + protected writeToDoExpression(expr: cs.ToDoExpression) { + this.write('/* TODO */'); + } + + protected writeIdentifier(expr: cs.Identifier) { + const name = this._context.getSymbolName(expr) ?? expr.text; + this.write(name); + } + + protected writeNullSafeExpression(expr: cs.NullSafeExpression) { + this.writeExpression(expr.expression); + this.write('?'); + } + + protected writeInvocationExpression(expr: cs.InvocationExpression) { + this.writeExpression(expr.expression); + if (expr.typeArguments) { + this.write('<'); + this.writeCommaSeparated(expr.typeArguments, t => this.writeType(t)); + this.write('>'); + } + this.write('('); + if (expr.arguments.length > 5) { + this.writeLine(); + this._indent++; + this.writeCommaSeparated(expr.arguments, a => { + this.writeExpression(a); + this.writeLine(); + }, true); + this._indent--; + this.writeLine(); + } else { + this.writeCommaSeparated(expr.arguments, a => this.writeExpression(a)); + } + this.write(')'); + } + + protected writeNullLiteral(expr: cs.NullLiteral) { + this.write('null'); + } + + protected writeBooleanLiteral(expr: cs.BooleanLiteral) { + this.write(cs.isTrueLiteral(expr) ? 'true' : 'false'); + } + + protected writeThisLiteral(expr: cs.ThisLiteral) { + this.write('this'); + } + + protected writeStringLiteral(expr: cs.StringLiteral) { + this.write(JSON.stringify(expr.text)); + } + + protected writeIsExpression(expr: cs.IsExpression) { + this.writeExpression(expr.expression); + this.write(' is '); + this.writeType(expr.type); + } + + protected writeParenthesizedExpression(expr: cs.ParenthesizedExpression) { + this.write('('); + this.writeExpression(expr.expression); + this.write(')'); + } + + protected writeTypeParameter(p: cs.TypeParameterDeclaration) { + this.write(p.name); + } + + protected writeTypeParameterConstraints(typeParameters: cs.TypeParameterDeclaration[] | undefined) { + if (typeParameters) { + this._indent++; + typeParameters.forEach(p => { + if (p.constraint) { + this.writeLine(); + this.write('where '); + this.write(p.name); + this.write(' : '); + this.writeType(p.constraint, false, false, true); + } + }); + this._indent--; + } + } + + protected writeTypeParameters(typeParameters: cs.TypeParameterDeclaration[] | undefined) { + if (typeParameters && typeParameters.length > 0) { + this.write('<'); + typeParameters.forEach((p, i) => { + if (i > 0) { + this.write(', '); + } + this.writeTypeParameter(p); + }); + this.write('>'); + } + } + + protected writeExpression(expr: cs.Expression) { + switch (expr.nodeType) { + case cs.SyntaxKind.PrefixUnaryExpression: + this.writePrefixUnaryExpression(expr as cs.PrefixUnaryExpression); + break; + case cs.SyntaxKind.PostfixUnaryExpression: + this.writePostfixUnaryExpression(expr as cs.PostfixUnaryExpression); + break; + case cs.SyntaxKind.NullLiteral: + this.writeNullLiteral(expr as cs.NullLiteral); + break; + case cs.SyntaxKind.FalseLiteral: + case cs.SyntaxKind.TrueLiteral: + this.writeBooleanLiteral(expr as cs.BooleanLiteral); + break; + case cs.SyntaxKind.ThisLiteral: + this.writeThisLiteral(expr as cs.ThisLiteral); + break; + case cs.SyntaxKind.BaseLiteralExpression: + this.writeBaseLiteralExpression(expr as cs.BaseLiteralExpression); + break; + case cs.SyntaxKind.StringLiteral: + this.writeStringLiteral(expr as cs.StringLiteral); + break; + case cs.SyntaxKind.AwaitExpression: + this.writeAwaitExpression(expr as cs.AwaitExpression); + break; + case cs.SyntaxKind.BinaryExpression: + this.writeBinaryExpression(expr as cs.BinaryExpression); + break; + case cs.SyntaxKind.ConditionalExpression: + this.writeConditionalExpression(expr as cs.ConditionalExpression); + break; + case cs.SyntaxKind.LambdaExpression: + this.writeLambdaExpression(expr as cs.LambdaExpression); + break; + case cs.SyntaxKind.NumericLiteral: + this.writeNumericLiteral(expr as cs.NumericLiteral); + break; + case cs.SyntaxKind.StringTemplateExpression: + this.writeStringTemplateExpression(expr as cs.StringTemplateExpression); + break; + case cs.SyntaxKind.IsExpression: + this.writeIsExpression(expr as cs.IsExpression); + break; + case cs.SyntaxKind.ParenthesizedExpression: + this.writeParenthesizedExpression(expr as cs.ParenthesizedExpression); + break; + case cs.SyntaxKind.ArrayCreationExpression: + this.writeArrayCreationExpression(expr as cs.ArrayCreationExpression); + break; + case cs.SyntaxKind.MemberAccessExpression: + this.writeMemberAccessExpression(expr as cs.MemberAccessExpression); + break; + case cs.SyntaxKind.AnonymousObjectCreationExpression: + this.writeAnonymousObjectCreationExpression(expr as cs.AnonymousObjectCreationExpression); + break; + case cs.SyntaxKind.AnonymousObjectProperty: + this.writeAnonymousObjectProperty(expr as cs.AnonymousObjectProperty); + break; + case cs.SyntaxKind.ElementAccessExpression: + this.writeElementAccessExpression(expr as cs.ElementAccessExpression); + break; + case cs.SyntaxKind.InvocationExpression: + this.writeInvocationExpression(expr as cs.InvocationExpression); + break; + case cs.SyntaxKind.NewExpression: + this.writeNewExpression(expr as cs.NewExpression); + break; + case cs.SyntaxKind.CastExpression: + this.writeCastExpression(expr as cs.CastExpression); + break; + case cs.SyntaxKind.NonNullExpression: + this.writeNonNullExpression(expr as cs.NonNullExpression); + break; + case cs.SyntaxKind.NullSafeExpression: + this.writeNullSafeExpression(expr as cs.NullSafeExpression); + break; + case cs.SyntaxKind.Identifier: + this.writeIdentifier(expr as cs.Identifier); + break; + case cs.SyntaxKind.ToDoExpression: + this.writeToDoExpression(expr as cs.ToDoExpression); + break; + case cs.SyntaxKind.DefaultExpression: + this.writeDefaultExpression(expr as cs.DefaultExpression); + break; + case cs.SyntaxKind.TypeOfExpression: + this.writeTypeOfExpression(expr as cs.TypeOfExpression); + break; + case cs.SyntaxKind.TypeReference: + this.writeType(expr as cs.TypeReference); + break; + default: + throw new Error(`Unhandled expression type: ${cs.SyntaxKind[expr.nodeType]}`); + } + } + + protected writeStatement(s: cs.Statement) { + switch (s.nodeType) { + case cs.SyntaxKind.EmptyStatement: + this.writeEmptyStatement(s as cs.EmptyStatement); + break; + case cs.SyntaxKind.Block: + this.writeBlock(s as cs.Block); + break; + case cs.SyntaxKind.VariableStatement: + this.writeVariableStatement(s as cs.VariableStatement); + break; + case cs.SyntaxKind.ExpressionStatement: + this.writeExpressionStatement(s as cs.ExpressionStatement); + break; + case cs.SyntaxKind.IfStatement: + this.writeIfStatement(s as cs.IfStatement); + break; + case cs.SyntaxKind.DoStatement: + this.writeDoStatement(s as cs.DoStatement); + break; + case cs.SyntaxKind.WhileStatement: + this.writeWhileStatement(s as cs.WhileStatement); + break; + case cs.SyntaxKind.ForStatement: + this.writeForStatement(s as cs.ForStatement); + break; + case cs.SyntaxKind.ForEachStatement: + this.writeForEachStatement(s as cs.ForEachStatement); + break; + case cs.SyntaxKind.BreakStatement: + this.writeBreakStatement(s as cs.BreakStatement); + break; + case cs.SyntaxKind.ContinueStatement: + this.writeContinueStatement(s as cs.ContinueStatement); + break; + case cs.SyntaxKind.ReturnStatement: + this.writeReturnStatement(s as cs.ReturnStatement); + break; + case cs.SyntaxKind.SwitchStatement: + this.writeSwitchStatement(s as cs.SwitchStatement); + break; + case cs.SyntaxKind.ThrowStatement: + this.writeThrowStatement(s as cs.ThrowStatement); + break; + case cs.SyntaxKind.TryStatement: + this.writeTryStatement(s as cs.TryStatement); + break; + } + } + + protected writeTryStatement(s: cs.TryStatement) { + this.writeLine('try'); + this.writeBlock(s.tryBlock); + if (s.catchClauses) { + s.catchClauses.forEach(c => this.writeCatchClause(c)); + } + if (s.finallyBlock) { + this.writeLine('finally'); + this.writeBlock(s.finallyBlock); + } + } + + protected writeThrowStatement(s: cs.ThrowStatement) { + this.write('throw'); + if (s.expression) { + this.write(' '); + this.writeExpression(s.expression); + } + this.writeSemicolon(); + } + + protected writeReturnStatement(r: cs.ReturnStatement) { + this.write('return'); + if (r.expression) { + this.write(' '); + this.writeExpression(r.expression); + } + this.writeSemicolon(); + } + + protected writeContinueStatement(_: cs.ContinueStatement) { + this.write('continue'); + this.writeSemicolon(); + } + + protected writeBreakStatement(_: cs.BreakStatement) { + this.write('break'); + this.writeSemicolon(); + } + + protected abstract writeCatchClause(c: cs.CatchClause): void; + protected abstract writeSwitchStatement(s: cs.SwitchStatement); + protected abstract writeForEachStatement(s: cs.ForEachStatement); + protected abstract writeForStatement(s: cs.ForStatement); + + protected writeWhileStatement(s: cs.WhileStatement) { + this.write('while ('); + this.writeExpression(s.expression); + this.writeLine(')'); + if (cs.isBlock(s.statement)) { + this.writeStatement(s.statement); + } else { + this._indent++; + this.writeStatement(s.statement); + this._indent--; + } + } + + protected writeDoStatement(s: cs.DoStatement) { + this.writeLine('do'); + this.writeStatement(s.statement); + this.write('while ('); + this.writeExpression(s.expression); + this.write(')'); + this.writeSemicolon(); + } + + protected writeIfStatement(s: cs.IfStatement) { + this.write('if ('); + this.writeExpression(s.expression); + this.writeLine(')'); + if (cs.isBlock(s.thenStatement)) { + this.writeStatement(s.thenStatement); + } else { + this._indent++; + this.writeStatement(s.thenStatement); + this._indent--; + } + + if (s.elseStatement) { + this.write('else '); + if (cs.isIfStatement(s.elseStatement)) { + this.writeStatement(s.elseStatement); + } else if (cs.isBlock(s.elseStatement)) { + this.writeLine(); + this.writeStatement(s.elseStatement); + } else { + this.writeLine(); + this._indent++; + this.writeStatement(s.elseStatement); + this._indent--; + } + } + } + + protected writeExpressionStatement(s: cs.ExpressionStatement) { + this.writeExpression(s.expression); + this.writeSemicolon(); + } + + protected writeVariableStatement(v: cs.VariableStatement) { + this.writeVariableDeclarationList(v.declarationList); + this.writeSemicolon(); + } + + protected writeEmptyStatement(_: cs.EmptyStatement) { + this.writeSemicolon(); + } + + protected abstract writeVariableDeclarationList(declarationList: cs.VariableDeclarationList); + protected abstract writeBlock(b: cs.Block); + + protected writeVisibility(visibility: cs.Visibility) { + switch (visibility) { + case cs.Visibility.Public: + this.write('public '); + break; + case cs.Visibility.Private: + this.write('private '); + break; + case cs.Visibility.Protected: + this.write('protected '); + break; + case cs.Visibility.Internal: + this.write('internal '); + break; + } + } + + protected writeDefaultExpression(expr: cs.DefaultExpression) { + this.write('default'); + if (expr.type) { + this.write('('); + this.writeType(expr.type); + this.write(')'); + } + } + + protected writePostfixUnaryExpression(expr: cs.PostfixUnaryExpression) { + this.writeExpression(expr.operand); + this.write(expr.operator); + } + + protected writeAnonymousObjectCreationExpression(expr: cs.AnonymousObjectCreationExpression) { + this.write('new'); + this.beginBlock(); + + expr.properties.forEach(p => this.writeAnonymousObjectProperty(p)); + + this.endBlock(); + } + + protected writeAnonymousObjectProperty(expr: cs.AnonymousObjectProperty) { + this.write(expr.name); + this.write(' = '); + this.writeExpression(expr.value); + this.writeLine(','); + } +} diff --git a/src.compiler/BuilderHelpers.ts b/src.compiler/BuilderHelpers.ts index ead0b0e9f..a52163f25 100644 --- a/src.compiler/BuilderHelpers.ts +++ b/src.compiler/BuilderHelpers.ts @@ -1,17 +1,69 @@ import * as ts from 'typescript'; +export function setMethodBody(m: ts.MethodDeclaration, body: ts.FunctionBody): ts.MethodDeclaration { + return ts.factory.updateMethodDeclaration( + m, + m.modifiers, + m.asteriskToken, + m.name, + m.questionToken, + m.typeParameters, + m.parameters, + m.type, + body + ); +} + +export function createNodeFromSource(source: string, kind: ts.SyntaxKind): T { + const sourceFile = ts.createSourceFile( + 'temp.ts', + source.trim(), + ts.ScriptTarget.Latest, + /*setParentNodes */ true, + ts.ScriptKind.TS + ); + const node = findNode(sourceFile, kind); + if (!node) { + throw new Error( + `Could not parse TS source to ${ts.SyntaxKind[kind]}, node count was ${sourceFile.getChildCount()}` + ); + } + return markNodeSynthesized(node) as T; +} + +function findNode(node: ts.Node, kind: ts.SyntaxKind): ts.Node | null { + if (node.kind === kind) { + return node; + } + + for (const c of node.getChildren()) { + const f = findNode(c, kind); + if (f) { + return f; + } + } + + return null; +} + export function addNewLines(stmts: ts.Statement[]) { return stmts.map(stmt => ts.addSyntheticTrailingComment(stmt, ts.SyntaxKind.SingleLineCommentTrivia, '', true)); } -export function getTypeWithNullableInfo(checker: ts.TypeChecker, node: ts.TypeNode | undefined) { - if(!node) { +export function getTypeWithNullableInfo( + checker: ts.TypeChecker, + node: ts.TypeNode | undefined, + allowUnionAsPrimitive: boolean +) { + if (!node) { return { isNullable: false, + isUnionType: false, type: {} as ts.Type }; } let isNullable = false; + let isUnionType = false; let type: ts.Type | null = null; if (ts.isUnionTypeNode(node)) { for (const t of node.types) { @@ -20,7 +72,18 @@ export function getTypeWithNullableInfo(checker: ts.TypeChecker, node: ts.TypeNo } else if (ts.isLiteralTypeNode(t) && t.literal.kind === ts.SyntaxKind.NullKeyword) { isNullable = true; } else if (type !== null) { - throw new Error('Multi union types on JSON settings not supported: ' + node.getSourceFile().fileName + ':' + node.getText()); + if (allowUnionAsPrimitive) { + isUnionType = true; + type = checker.getTypeAtLocation(node); + break; + } else { + throw new Error( + 'Multi union types on JSON settings not supported: ' + + node.getSourceFile().fileName + + ':' + + node.getText() + ); + } } else { type = checker.getTypeAtLocation(t); } @@ -31,6 +94,7 @@ export function getTypeWithNullableInfo(checker: ts.TypeChecker, node: ts.TypeNo return { isNullable, + isUnionType, type: type as ts.Type }; } @@ -46,13 +110,15 @@ export function unwrapArrayItemType(type: ts.Type, typeChecker: ts.TypeChecker): if (type.isUnion()) { const nonNullable = typeChecker.getNonNullableType(type); + if (type === nonNullable) { + return null; + } return unwrapArrayItemType(nonNullable, typeChecker); } return null; } - export function isPrimitiveType(type: ts.Type | null) { if (!type) { return false; @@ -85,7 +151,7 @@ export function isNumberType(type: ts.Type | null) { if (hasFlag(type, ts.TypeFlags.Number)) { return true; } - + return false; } @@ -116,4 +182,15 @@ export function hasFlag(type: ts.Type, flag: ts.TypeFlags): boolean { export function isMap(type: ts.Type | null): boolean { return !!(type && type.symbol?.name === 'Map'); -} \ No newline at end of file +} + +function markNodeSynthesized(node: ts.Node): ts.Node { + for (const c of node.getChildren()) { + markNodeSynthesized(c); + } + ts.setTextRange(node, { + pos: -1, + end: -1 + }); + return node; +} diff --git a/src.compiler/csharp/CSharpAst.ts b/src.compiler/csharp/CSharpAst.ts index dd7c531e1..8a356f203 100644 --- a/src.compiler/csharp/CSharpAst.ts +++ b/src.compiler/csharp/CSharpAst.ts @@ -8,20 +8,20 @@ export enum SyntaxKind { ClassDeclaration, EnumDeclaration, InterfaceDeclaration, - DelegateDeclaration, TypeParameterDeclaration, MethodDeclaration, ConstructorDeclaration, FieldDeclaration, PropertyDeclaration, - EventDeclaration, PropertyAccessorDeclaration, ParameterDeclaration, UnresolvedTypeNode, TypeReference, + FunctionTypeNode, PrimitiveTypeNode, EnumMember, ArrayTypeNode, + MapTypeNode, Block, EmptyStatement, @@ -36,7 +36,6 @@ export enum SyntaxKind { ContinueStatement, ReturnStatement, SwitchStatement, - LabeledStatement, ThrowStatement, TryStatement, @@ -77,7 +76,7 @@ export enum SyntaxKind { DefaultExpression, ToDoExpression, TypeOfExpression, - + Attribute } @@ -96,7 +95,6 @@ export interface SourceFile extends Node { } export interface UsingDeclaration extends Node { - typeAlias?: string; namespaceOrTypeName: string; } @@ -105,7 +103,7 @@ export interface NamespaceDeclaration extends Node { declarations: NamespaceMember[]; } -type NamespaceMember = ClassDeclaration | EnumDeclaration | InterfaceDeclaration | DelegateDeclaration; +export type NamespaceMember = ClassDeclaration | EnumDeclaration | InterfaceDeclaration; export enum Visibility { None, @@ -115,7 +113,7 @@ export enum Visibility { Internal } -export interface DocumentedElement { +export interface DocumentedElement extends Node { documentation?: string; } export interface AttributedElement { @@ -123,8 +121,8 @@ export interface AttributedElement { } export interface Attribute extends Node { - type: TypeNode, - arguments?: Expression[] + type: TypeNode; + arguments?: Expression[]; } export interface NamedElement { @@ -141,6 +139,7 @@ export interface NamedTypeDeclaration extends NamedElement, DocumentedElement, N typeParameters?: TypeParameterDeclaration[]; visibility: Visibility; partial: boolean; + hasVirtualMembersOrSubClasses: boolean; } export interface ClassDeclaration extends NamedTypeDeclaration { @@ -155,7 +154,6 @@ export type ClassMember = | MethodDeclaration | FieldDeclaration | PropertyDeclaration - | EventDeclaration | NamedTypeDeclaration; export interface EnumDeclaration extends NamedTypeDeclaration { @@ -171,7 +169,7 @@ export interface InterfaceDeclaration extends NamedTypeDeclaration { members: InterfaceMember[]; } -export type InterfaceMember = MethodDeclaration | PropertyDeclaration | EventDeclaration; +export type InterfaceMember = MethodDeclaration | PropertyDeclaration; export interface MemberDeclaration extends NamedElement, DocumentedElement, Node { visibility: Visibility; @@ -188,6 +186,7 @@ export interface MethodDeclaration extends MethodDeclarationBase, AttributedElem isVirtual: boolean; isOverride: boolean; isAbstract: boolean; + partial: boolean; returnType: TypeNode; parameters: ParameterDeclaration[]; body?: Block | Expression; @@ -220,15 +219,6 @@ export interface PropertyAccessorDeclaration extends Node { body?: Block | Expression; } -export interface EventDeclaration extends MemberDeclaration { - eventType: TypeNode; -} - -export interface DelegateDeclaration extends NamedTypeDeclaration { - returnType: TypeNode; - parameters: ParameterDeclaration[]; -} - export interface ParameterDeclaration extends NamedElement, Node, DocumentedElement { type?: TypeNode; initializer?: Expression; @@ -248,7 +238,7 @@ export interface UnresolvedTypeNode extends TypeNode { typeArguments?: UnresolvedTypeNode[]; } -export type TypeReferenceType = NamedTypeDeclaration | TypeParameterDeclaration | PrimitiveTypeNode | string; +export type TypeReferenceType = NamedTypeDeclaration | TypeParameterDeclaration | TypeNode | string; export interface TypeReference extends TypeNode { reference: TypeReferenceType; typeArguments?: TypeNode[]; @@ -258,6 +248,18 @@ export interface ArrayTypeNode extends TypeNode { elementType: TypeNode; } +export interface MapTypeNode extends TypeNode { + keyType: TypeNode; + keyIsValueType: boolean; + valueType: TypeNode; + valueIsValueType:boolean; +} + +export interface FunctionTypeNode extends TypeNode { + parameterTypes: TypeNode[]; + returnType: TypeNode; +} + export enum PrimitiveType { Bool, String, @@ -318,6 +320,7 @@ export interface ConditionalExpression extends Node { export interface LambdaExpression extends Node { parameters: ParameterDeclaration[]; body: Block | Expression; + returnType: TypeNode; } export interface NumericLiteral extends Node { @@ -361,6 +364,7 @@ export interface AnonymousObjectProperty extends Node { export interface ElementAccessExpression extends Node { expression: Expression; argumentExpression: Expression; + nullSafe: boolean; } export interface InvocationExpression extends Node { @@ -495,3 +499,82 @@ export interface CatchClause extends Node { variableDeclaration: VariableDeclaration; block: Block; } + +// Node Tests +export function isNode(node: any): node is Node { return typeof(node) === 'object' && 'nodeType' in node; } +export function isSourceFile(node: Node): node is SourceFile { return node.nodeType === SyntaxKind.SourceFile; } +export function isUsingDeclaration(node: Node): node is UsingDeclaration { return node.nodeType === SyntaxKind.UsingDeclaration; } +export function isNamespaceDeclaration(node: Node): node is NamespaceDeclaration { return node.nodeType === SyntaxKind.NamespaceDeclaration; } +export function isClassDeclaration(node: Node): node is ClassDeclaration { return node.nodeType === SyntaxKind.ClassDeclaration; } +export function isEnumDeclaration(node: Node): node is EnumDeclaration { return node.nodeType === SyntaxKind.EnumDeclaration; } +export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { return node.nodeType === SyntaxKind.InterfaceDeclaration; } +export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { return node.nodeType === SyntaxKind.TypeParameterDeclaration; } +export function isMethodDeclaration(node: Node): node is MethodDeclaration { return node.nodeType === SyntaxKind.MethodDeclaration; } +export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { return node.nodeType === SyntaxKind.ConstructorDeclaration; } +export function isFieldDeclaration(node: Node): node is FieldDeclaration { return node.nodeType === SyntaxKind.FieldDeclaration; } +export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { return node.nodeType === SyntaxKind.PropertyDeclaration; } +export function isPropertyAccessorDeclaration(node: Node): node is PropertyAccessorDeclaration { return node.nodeType === SyntaxKind.PropertyAccessorDeclaration; } +export function isParameterDeclaration(node: Node): node is ParameterDeclaration { return node.nodeType === SyntaxKind.ParameterDeclaration; } +export function isUnresolvedTypeNode(node: Node): node is UnresolvedTypeNode { return node.nodeType === SyntaxKind.UnresolvedTypeNode; } +export function isTypeReference(node: Node): node is TypeReference { return node.nodeType === SyntaxKind.TypeReference; } +export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { return node.nodeType === SyntaxKind.FunctionTypeNode; } +export function isPrimitiveTypeNode(node: Node): node is PrimitiveTypeNode { return node.nodeType === SyntaxKind.PrimitiveTypeNode; } +export function isEnumMember(node: Node): node is EnumMember { return node.nodeType === SyntaxKind.EnumMember; } +export function isArrayTypeNode(node: Node): node is ArrayTypeNode { return node.nodeType === SyntaxKind.ArrayTypeNode; } +export function isMapTypeNode(node: Node): node is MapTypeNode { return node.nodeType === SyntaxKind.MapTypeNode; } + +export function isBlock(node: Node): node is Block { return node.nodeType === SyntaxKind.Block; } +export function isEmptyStatement(node: Node): node is EmptyStatement { return node.nodeType === SyntaxKind.EmptyStatement; } +export function isVariableStatement(node: Node): node is VariableStatement { return node.nodeType === SyntaxKind.VariableStatement; } +export function isExpressionStatement(node: Node): node is ExpressionStatement { return node.nodeType === SyntaxKind.ExpressionStatement; } +export function isIfStatement(node: Node): node is IfStatement { return node.nodeType === SyntaxKind.IfStatement; } +export function isDoStatement(node: Node): node is DoStatement { return node.nodeType === SyntaxKind.DoStatement; } +export function isWhileStatement(node: Node): node is WhileStatement { return node.nodeType === SyntaxKind.WhileStatement; } +export function isForStatement(node: Node): node is ForStatement { return node.nodeType === SyntaxKind.ForStatement; } +export function isForEachStatement(node: Node): node is ForEachStatement { return node.nodeType === SyntaxKind.ForEachStatement; } +export function isBreakStatement(node: Node): node is BreakStatement { return node.nodeType === SyntaxKind.BreakStatement; } +export function isContinueStatement(node: Node): node is ContinueStatement { return node.nodeType === SyntaxKind.ContinueStatement; } +export function isReturnStatement(node: Node): node is ReturnStatement { return node.nodeType === SyntaxKind.ReturnStatement; } +export function isSwitchStatement(node: Node): node is SwitchStatement { return node.nodeType === SyntaxKind.SwitchStatement; } +export function isThrowStatement(node: Node): node is ThrowStatement { return node.nodeType === SyntaxKind.ThrowStatement; } +export function isTryStatement(node: Node): node is TryStatement { return node.nodeType === SyntaxKind.TryStatement; } + +export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { return node.nodeType === SyntaxKind.VariableDeclarationList; } +export function isVariableDeclaration(node: Node): node is VariableDeclaration { return node.nodeType === SyntaxKind.VariableDeclaration; } +export function isDeconstructDeclaration(node: Node): node is DeconstructDeclaration { return node.nodeType === SyntaxKind.DeconstructDeclaration; } +export function isCaseClause(node: Node): node is CaseClause { return node.nodeType === SyntaxKind.CaseClause; } +export function isDefaultClause(node: Node): node is DefaultClause { return node.nodeType === SyntaxKind.DefaultClause; } +export function isCatchClause(node: Node): node is CatchClause { return node.nodeType === SyntaxKind.CatchClause; } + +export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { return node.nodeType === SyntaxKind.PrefixUnaryExpression; } +export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { return node.nodeType === SyntaxKind.PostfixUnaryExpression; } +export function isNullLiteral(node: Node): node is NullLiteral { return node.nodeType === SyntaxKind.NullLiteral; } +export function isTrueLiteral(node: Node): node is BooleanLiteral { return node.nodeType === SyntaxKind.TrueLiteral; } +export function isFalseLiteral(node: Node): node is BooleanLiteral { return node.nodeType === SyntaxKind.FalseLiteral; } +export function isThisLiteral(node: Node): node is ThisLiteral { return node.nodeType === SyntaxKind.ThisLiteral; } +export function isBaseLiteralExpression(node: Node): node is BaseLiteralExpression { return node.nodeType === SyntaxKind.BaseLiteralExpression; } +export function isStringLiteral(node: Node): node is StringLiteral { return node.nodeType === SyntaxKind.StringLiteral; } +export function isAwaitExpression(node: Node): node is AwaitExpression { return node.nodeType === SyntaxKind.AwaitExpression; } +export function isBinaryExpression(node: Node): node is BinaryExpression { return node.nodeType === SyntaxKind.BinaryExpression; } +export function isConditionalExpression(node: Node): node is ConditionalExpression { return node.nodeType === SyntaxKind.ConditionalExpression; } +export function isLambdaExpression(node: Node): node is LambdaExpression { return node.nodeType === SyntaxKind.LambdaExpression; } +export function isNumericLiteral(node: Node): node is NumericLiteral { return node.nodeType === SyntaxKind.NumericLiteral; } +export function isStringTemplateExpression(node: Node): node is StringTemplateExpression { return node.nodeType === SyntaxKind.StringTemplateExpression; } +export function isIsExpression(node: Node): node is IsExpression { return node.nodeType === SyntaxKind.IsExpression; } +export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { return node.nodeType === SyntaxKind.ParenthesizedExpression; } +export function isArrayCreationExpression(node: Node): node is ArrayCreationExpression { return node.nodeType === SyntaxKind.ArrayCreationExpression; } +export function isMemberAccessExpression(node: Node): node is MemberAccessExpression { return node.nodeType === SyntaxKind.MemberAccessExpression; } +export function isAnonymousObjectCreationExpression(node: Node): node is AnonymousObjectCreationExpression { return node.nodeType === SyntaxKind.AnonymousObjectCreationExpression; } +export function isAnonymousObjectProperty(node: Node): node is AnonymousObjectProperty { return node.nodeType === SyntaxKind.AnonymousObjectProperty; } +export function isElementAccessExpression(node: Node): node is ElementAccessExpression { return node.nodeType === SyntaxKind.ElementAccessExpression; } +export function isInvocationExpression(node: Node): node is InvocationExpression { return node.nodeType === SyntaxKind.InvocationExpression; } +export function isNewExpression(node: Node): node is NewExpression { return node.nodeType === SyntaxKind.NewExpression; } +export function isCastExpression(node: Node): node is CastExpression { return node.nodeType === SyntaxKind.CastExpression; } +export function isNonNullExpression(node: Node): node is NonNullExpression { return node.nodeType === SyntaxKind.NonNullExpression; } +export function isNullSafeExpression(node: Node): node is NullSafeExpression { return node.nodeType === SyntaxKind.NullSafeExpression; } +export function isIdentifier(node: Node): node is Identifier { return node.nodeType === SyntaxKind.Identifier; } +export function isDefaultExpression(node: Node): node is DefaultExpression { return node.nodeType === SyntaxKind.DefaultExpression; } +export function isToDoExpression(node: Node): node is ToDoExpression { return node.nodeType === SyntaxKind.ToDoExpression; } +export function isTypeOfExpression(node: Node): node is TypeOfExpression { return node.nodeType === SyntaxKind.TypeOfExpression; } + +export function isAttribute(node: Node): node is Attribute { return node.nodeType === SyntaxKind.Attribute; } \ No newline at end of file diff --git a/src.compiler/csharp/CSharpAstPrinter.ts b/src.compiler/csharp/CSharpAstPrinter.ts index 69f306e94..d765da499 100644 --- a/src.compiler/csharp/CSharpAstPrinter.ts +++ b/src.compiler/csharp/CSharpAstPrinter.ts @@ -1,34 +1,14 @@ import * as cs from './CSharpAst'; import * as ts from 'typescript'; -import * as path from 'path'; -import * as fs from 'fs'; import CSharpEmitterContext from './CSharpEmitterContext'; +import AstPrinterBase from '../AstPrinterBase'; -export default class CSharpAstPrinter { - private _sourceFile: cs.SourceFile; - private _fileHandle!: number; - private _isStartOfLine: boolean = true; - private _indent: number = 0; - private _context: CSharpEmitterContext; - - public diagnostics: ts.Diagnostic[] = []; - +export default class CSharpAstPrinter extends AstPrinterBase { public constructor(sourceFile: cs.SourceFile, context: CSharpEmitterContext) { - this._sourceFile = sourceFile; - this._context = context; - } - - public print() { - fs.mkdirSync(path.dirname(this._sourceFile.fileName), { recursive: true }); - this._fileHandle = fs.openSync(this._sourceFile.fileName, 'w'); - try { - this.writeSourceFile(this._sourceFile); - } finally { - fs.closeSync(this._fileHandle); - } + super(sourceFile, context); } - private writeSourceFile(sourceFile: cs.SourceFile) { + protected writeSourceFile(sourceFile: cs.SourceFile) { this.writeLine('// '); this.writeLine('// This code was auto-generated.'); this.writeLine('// Changes to this file may cause incorrect behavior and will be lost if'); @@ -45,50 +25,22 @@ export default class CSharpAstPrinter { this.writeNamespace(sourceFile.namespace); } - private writeNamespace(namespace: cs.NamespaceDeclaration) { + protected writeNamespace(namespace: cs.NamespaceDeclaration) { this.writeLine(`namespace ${namespace.namespace}`); this.beginBlock(); - - for (const declaration of namespace.declarations) { - if (!declaration.skipEmit) { - switch (declaration.nodeType) { - case cs.SyntaxKind.ClassDeclaration: - this.writeClassDeclaration(declaration as cs.ClassDeclaration); - break; - case cs.SyntaxKind.EnumDeclaration: - this.writeEnumDeclaration(declaration as cs.EnumDeclaration); - break; - case cs.SyntaxKind.InterfaceDeclaration: - this.writeInterfaceDeclaration(declaration as cs.InterfaceDeclaration); - break; - case cs.SyntaxKind.DelegateDeclaration: - this.writeDelegateDeclaration(declaration as cs.DelegateDeclaration); - break; - } - } - } - + this.writeNamespaceMembers(namespace.declarations); this.endBlock(); } - private writeDelegateDeclaration(d: cs.DelegateDeclaration) { - this.writeDocumentation(d); - this.writeVisibility(d.visibility); - this.writeType(d.returnType); - this.write(` ${d.name}`); - this.writeTypeParameters(d.typeParameters); - this.writeParameters(d.parameters); - this.writeLine(';'); - } - - private writeDocumentation(d: cs.DocumentedElement) { + protected writeDocumentation(d: cs.DocumentedElement) { if (d.documentation) { this.writeLine('/// '); this.writeDocumentationLines(d.documentation, true); this.writeLine('/// '); } } - private writeDocumentationLines(documentation: string, multiLine: boolean) { + + protected writeDocumentationLines(documentation: string, multiLine: boolean) { const lines = documentation.split('\n'); if (lines.length > 1 || multiLine) { if (!this._isStartOfLine) { @@ -105,25 +57,11 @@ export default class CSharpAstPrinter { } } } - private escapeXmlDoc(s: string): string { + protected escapeXmlDoc(s: string): string { return s.replace(/&/g, '&').replace(//g, '>'); } - private writeParameters(parameters: cs.ParameterDeclaration[]) { - this.write('('); - this.writeCommaSeparated(parameters, p => this.writeParameter(p)); - this.write(')'); - } - private writeCommaSeparated(values: T[], write: (p: T) => void) { - values.forEach((v, i) => { - if (i > 0) { - this.write(', '); - } - write(v); - }); - } - - private writeParameter(p: cs.ParameterDeclaration) { + protected writeParameter(p: cs.ParameterDeclaration) { if (p.params) { this.write('params '); } @@ -140,7 +78,7 @@ export default class CSharpAstPrinter { } } - private writeInterfaceDeclaration(d: cs.InterfaceDeclaration) { + protected writeInterfaceDeclaration(d: cs.InterfaceDeclaration) { this.writeDocumentation(d); this.writeVisibility(d.visibility); @@ -165,7 +103,7 @@ export default class CSharpAstPrinter { this.endBlock(); } - private writeEnumDeclaration(d: cs.EnumDeclaration) { + protected writeEnumDeclaration(d: cs.EnumDeclaration) { this.writeDocumentation(d); this.writeVisibility(d.visibility); this.write(`enum ${d.name}`); @@ -176,7 +114,8 @@ export default class CSharpAstPrinter { this.endBlock(); } - private writeEnumMember(m: cs.EnumMember): void { + + protected writeEnumMember(m: cs.EnumMember): void { this.writeDocumentation(m); this.write(m.name); if (m.initializer) { @@ -186,7 +125,7 @@ export default class CSharpAstPrinter { this.writeLine(','); } - private writeClassDeclaration(d: cs.ClassDeclaration) { + protected writeClassDeclaration(d: cs.ClassDeclaration) { this.writeDocumentation(d); this.writeAttributes(d); this.writeVisibility(d.visibility); @@ -225,7 +164,7 @@ export default class CSharpAstPrinter { let hasConstuctor = false; d.members.forEach(m => { this.writeMember(m); - if (m.nodeType === cs.SyntaxKind.ConstructorDeclaration && !(m as cs.ConstructorDeclaration).isStatic) { + if (cs.isConstructorDeclaration(m) && !m.isStatic) { hasConstuctor = true; } }); @@ -237,19 +176,17 @@ export default class CSharpAstPrinter { if (typeof baseClass === 'string') { constructorDeclaration = undefined; break; - } else if (baseClass.nodeType === cs.SyntaxKind.ClassDeclaration) { - const baseClassDeclaration = baseClass as cs.ClassDeclaration; - constructorDeclaration = baseClassDeclaration.members.find( - m => m.nodeType === cs.SyntaxKind.ConstructorDeclaration + } else if (cs.isClassDeclaration(baseClass)) { + constructorDeclaration = baseClass.members.find(m => + cs.isConstructorDeclaration(m) ) as cs.ConstructorDeclaration; if (constructorDeclaration) { break; } baseClass = - baseClassDeclaration.baseClass && - baseClassDeclaration.baseClass.nodeType === cs.SyntaxKind.TypeReference - ? (baseClassDeclaration.baseClass as cs.TypeReference).reference + baseClass.baseClass && cs.isTypeReference(baseClass.baseClass) + ? baseClass.baseClass.reference : undefined; } else { constructorDeclaration = undefined; @@ -278,12 +215,12 @@ export default class CSharpAstPrinter { defaultConstructor.parameters = constructorDeclaration.parameters; defaultConstructor.baseConstructorArguments = constructorDeclaration.parameters.map( p => - ({ - parent: defaultConstructor, - nodeType: cs.SyntaxKind.Identifier, - text: p.name, - tsNode: defaultConstructor.tsNode - } as cs.Identifier) + ({ + parent: defaultConstructor, + nodeType: cs.SyntaxKind.Identifier, + text: p.name, + tsNode: defaultConstructor.tsNode + } as cs.Identifier) ); this.writeMember(defaultConstructor); } @@ -292,13 +229,7 @@ export default class CSharpAstPrinter { this.endBlock(); } - public writeAttributes(d: cs.AttributedElement) { - if (d.attributes) { - d.attributes.forEach(a => this.writeAttribute(a)); - } - } - - public writeAttribute(a: cs.Attribute): void { + protected writeAttribute(a: cs.Attribute): void { this.write('['); this.writeType(a.type); if (a.arguments && a.arguments.length > 0) { @@ -309,59 +240,9 @@ export default class CSharpAstPrinter { this.writeLine(']'); } - private writeMember(member: cs.Node) { - if (member.skipEmit) { - return; - } - - switch (member.nodeType) { - case cs.SyntaxKind.FieldDeclaration: - this.writeFieldDeclarat1on(member as cs.FieldDeclaration); - break; - case cs.SyntaxKind.PropertyDeclaration: - this.writePropertyDeclaration(member as cs.PropertyDeclaration); - break; - case cs.SyntaxKind.ConstructorDeclaration: - this.writeConstructorDeclaration(member as cs.ConstructorDeclaration); - break; - case cs.SyntaxKind.MethodDeclaration: - this.writeMethodDeclaration(member as cs.MethodDeclaration); - break; - case cs.SyntaxKind.EventDeclaration: - this.writeEventDeclaration(member as cs.EventDeclaration); - break; - case cs.SyntaxKind.ClassDeclaration: - this.writeClassDeclaration(member as cs.ClassDeclaration); - break; - case cs.SyntaxKind.EnumDeclaration: - this.writeEnumDeclaration(member as cs.EnumDeclaration); - break; - case cs.SyntaxKind.InterfaceDeclaration: - this.writeInterfaceDeclaration(member as cs.InterfaceDeclaration); - break; - case cs.SyntaxKind.DelegateDeclaration: - this.writeDelegateDeclaration(member as cs.DelegateDeclaration); - break; - } - this.writeLine(); - } - - private writeEventDeclaration(d: cs.EventDeclaration) { - throw new Error('Method not implemented.'); - } - - private writeMethodDeclaration(d: cs.MethodDeclaration) { + protected writeMethodDeclaration(d: cs.MethodDeclaration) { this.writeDocumentation(d); - for (const p of d.parameters) { - if (p.documentation) { - this.write(`/// `); - this.writeDocumentationLines(p.documentation, false); - if (this._isStartOfLine) { - this.write('/// '); - } - this.writeLine(''); - } - } + this.writeParameterDocumentation(d); this.writeAttributes(d); this.writeVisibility(d.visibility); @@ -377,20 +258,15 @@ export default class CSharpAstPrinter { if (d.isAbstract) { this.write('abstract '); } - - if (d.isVirtual) { + else if (d.isVirtual) { this.write('virtual '); } - - if (d.isOverride) { + else if (d.isOverride) { this.write('override '); } if (d.isAsync) { - if ( - d.returnType.nodeType === cs.SyntaxKind.PrimitiveTypeNode && - (d.returnType as cs.PrimitiveTypeNode).type === cs.PrimitiveType.Void - ) { + if (cs.isPrimitiveTypeNode(d.returnType) && d.returnType.type === cs.PrimitiveType.Void) { this.write('System.Threading.Tasks.Task'); } else { this.write('System.Threading.Tasks.Task<'); @@ -409,27 +285,24 @@ export default class CSharpAstPrinter { this.writeBody(d.body); } - private writeTypeParameterConstraints(typeParameters: cs.TypeParameterDeclaration[] | undefined) { - if (typeParameters) { - this._indent++; - typeParameters.forEach(p => { - if (p.constraint) { - this.writeLine(); - this.write('where '); - this.write(p.name); - this.write(' : '); - this.writeType(p.constraint, false, false, true); + protected writeParameterDocumentation(d: cs.MethodDeclaration) { + for (const p of d.parameters) { + if (p.documentation) { + this.write(`/// `); + this.writeDocumentationLines(p.documentation, false); + if (this._isStartOfLine) { + this.write('/// '); } - }); - this._indent--; + this.writeLine(''); + } } } - private writeBody(body: cs.Expression | cs.Block | undefined) { + protected writeBody(body: cs.Expression | cs.Block | undefined) { if (body) { - if (body.nodeType === cs.SyntaxKind.Block) { + if (cs.isBlock(body)) { this.writeLine(); - this.writeBlock(body as cs.Block); + this.writeBlock(body); } else { this.write(' => '); this.writeExpression(body as cs.Expression); @@ -439,11 +312,11 @@ export default class CSharpAstPrinter { } } - private writeConstructorDeclaration(d: cs.ConstructorDeclaration) { + protected writeConstructorDeclaration(d: cs.ConstructorDeclaration) { this.writeDocumentation(d); this.writeVisibility(d.visibility); if (d.isStatic) { - this.write('static ') + this.write('static '); } this.write(`${(d.parent as cs.ClassDeclaration).name}`); this.writeParameters(d.parameters); @@ -460,7 +333,7 @@ export default class CSharpAstPrinter { this.writeBody(d.body); } - private writePropertyDeclaration(d: cs.PropertyDeclaration) { + protected writePropertyDeclaration(d: cs.PropertyDeclaration) { this.writeDocumentation(d); this.writeVisibility(d.visibility); @@ -476,12 +349,10 @@ export default class CSharpAstPrinter { if (d.isAbstract) { this.write('abstract '); } - - if (d.isVirtual) { + else if (d.isVirtual) { this.write('virtual '); } - - if (d.isOverride) { + else if (d.isOverride) { this.write('override '); } } @@ -512,30 +383,13 @@ export default class CSharpAstPrinter { this.writeLine(';'); } } - private canBeConstant(d: cs.PropertyDeclaration): boolean { - return ( - d.isStatic && - !d.setAccessor && - d.type.nodeType === cs.SyntaxKind.PrimitiveTypeNode && - !!d.initializer && - (!d.getAccessor || !d.getAccessor.body) - ); - } - private writePropertyAsField(d: cs.PropertyDeclaration) { - if (d.parent!.nodeType === cs.SyntaxKind.ClassDeclaration && d.visibility === cs.Visibility.Private && - (!d.getAccessor || !d.getAccessor.body)) { - return true; - } - return this.canBeConstant(d); - } - - private writePropertyAccessor(accessor: cs.PropertyAccessorDeclaration) { + protected writePropertyAccessor(accessor: cs.PropertyAccessorDeclaration) { this.write(accessor.keyword); this.writeBody(accessor.body); } - private writeFieldDeclarat1on(d: cs.FieldDeclaration) { + protected writeFieldDeclarat1on(d: cs.FieldDeclaration) { this.writeDocumentation(d); this.writeVisibility(d.visibility); @@ -560,7 +414,12 @@ export default class CSharpAstPrinter { this.writeLine(';'); } - private writeType(type: cs.TypeNode, forNew: boolean = false, asNativeArray: boolean = false, forTypeConstraint: boolean = false) { + protected writeType( + type: cs.TypeNode, + forNew: boolean = false, + asNativeArray: boolean = false, + forTypeConstraint: boolean = false + ) { switch (type.nodeType) { case cs.SyntaxKind.PrimitiveTypeNode: if (forTypeConstraint) { @@ -613,8 +472,9 @@ export default class CSharpAstPrinter { this.writeType(arrayType.elementType); this.write('[]'); } else { - const isDynamicArray = arrayType.elementType.nodeType == cs.SyntaxKind.PrimitiveTypeNode - && (arrayType.elementType as cs.PrimitiveTypeNode).type == cs.PrimitiveType.Dynamic; + const isDynamicArray = + cs.isPrimitiveTypeNode(arrayType.elementType) && + arrayType.elementType.type === cs.PrimitiveType.Dynamic; if (isDynamicArray && !forNew) { this.write('System.Collections.IList'); } else { @@ -626,9 +486,45 @@ export default class CSharpAstPrinter { this.writeType(arrayType.elementType); this.write('>'); } - } + break; + case cs.SyntaxKind.MapTypeNode: + const mapType = type as cs.MapTypeNode; + if (!mapType.valueIsValueType) { + this.write('AlphaTab.Core.EcmaScript.Map<'); + } else { + this.write('AlphaTab.Core.EcmaScript.ValueTypeMap<'); + } + this.writeType(mapType.keyType); + this.write(', '); + this.writeType(mapType.valueType); + this.write('>'); + break; + case cs.SyntaxKind.FunctionTypeNode: + const functionType = type as cs.FunctionTypeNode; + if ( + cs.isPrimitiveTypeNode(functionType.returnType) && + functionType.returnType.type === cs.PrimitiveType.Void + ) { + this.write('System.Action'); + if (functionType.parameterTypes.length > 0) { + this.write('<'); + this.writeCommaSeparated(functionType.parameterTypes, p => this.writeType(p)); + this.write('>'); + } + } else { + this.write('System.Func'); + this.write('<'); + if (functionType.parameterTypes.length > 0) { + this.writeCommaSeparated(functionType.parameterTypes, p => this.writeType(p)); + this.write(', '); + this.writeType(functionType.returnType); + } else { + this.writeType(functionType.returnType); + } + this.write('>'); + } break; case cs.SyntaxKind.TypeReference: const typeReference = type as cs.TypeReference; @@ -648,7 +544,6 @@ export default class CSharpAstPrinter { case cs.SyntaxKind.ClassDeclaration: case cs.SyntaxKind.InterfaceDeclaration: case cs.SyntaxKind.EnumDeclaration: - case cs.SyntaxKind.DelegateDeclaration: this.write(this._context.getFullName(type as cs.NamedTypeDeclaration)); break; case cs.SyntaxKind.TypeParameterDeclaration: @@ -666,127 +561,7 @@ export default class CSharpAstPrinter { } } - private writeTypeParameters(typeParameters: cs.TypeParameterDeclaration[] | undefined) { - if (typeParameters && typeParameters.length > 0) { - this.write('<'); - typeParameters.forEach((p, i) => { - if (i > 0) { - this.write(', '); - } - this.writeTypeParameter(p); - }); - this.write('>'); - } - } - - private writeTypeParameter(p: cs.TypeParameterDeclaration) { - this.write(p.name); - } - - private writeExpression(expr: cs.Expression) { - switch (expr.nodeType) { - case cs.SyntaxKind.PrefixUnaryExpression: - this.writePrefixUnaryExpression(expr as cs.PrefixUnaryExpression); - break; - case cs.SyntaxKind.PostfixUnaryExpression: - this.writePostfixUnaryExpression(expr as cs.PostfixUnaryExpression); - break; - case cs.SyntaxKind.NullLiteral: - this.writeNullLiteral(expr as cs.NullLiteral); - break; - case cs.SyntaxKind.FalseLiteral: - case cs.SyntaxKind.TrueLiteral: - this.writeBooleanLiteral(expr as cs.BooleanLiteral); - break; - case cs.SyntaxKind.ThisLiteral: - this.writeThisLiteral(expr as cs.ThisLiteral); - break; - case cs.SyntaxKind.BaseLiteralExpression: - this.writeBaseLiteralExpression(expr as cs.BaseLiteralExpression); - break; - case cs.SyntaxKind.StringLiteral: - this.writeStringLiteral(expr as cs.StringLiteral); - break; - case cs.SyntaxKind.AwaitExpression: - this.writeAwaitExpression(expr as cs.AwaitExpression); - break; - case cs.SyntaxKind.BinaryExpression: - this.writeBinaryExpression(expr as cs.BinaryExpression); - break; - case cs.SyntaxKind.ConditionalExpression: - this.writeConditionalExpression(expr as cs.ConditionalExpression); - break; - case cs.SyntaxKind.LambdaExpression: - this.writeLambdaExpression(expr as cs.LambdaExpression); - break; - case cs.SyntaxKind.NumericLiteral: - this.writeNumericLiteral(expr as cs.NumericLiteral); - break; - case cs.SyntaxKind.StringTemplateExpression: - this.writeStringTemplateExpression(expr as cs.StringTemplateExpression); - break; - case cs.SyntaxKind.IsExpression: - this.writeIsExpression(expr as cs.IsExpression); - break; - case cs.SyntaxKind.ParenthesizedExpression: - this.writeParenthesizedExpression(expr as cs.ParenthesizedExpression); - break; - case cs.SyntaxKind.ArrayCreationExpression: - this.writeArrayCreationExpression(expr as cs.ArrayCreationExpression); - break; - case cs.SyntaxKind.MemberAccessExpression: - this.writeMemberAccessExpression(expr as cs.MemberAccessExpression); - break; - case cs.SyntaxKind.AnonymousObjectCreationExpression: - this.writeAnonymousObjectCreationExpression(expr as cs.AnonymousObjectCreationExpression); - break; - case cs.SyntaxKind.AnonymousObjectProperty: - this.writeAnonymousObjectProperty(expr as cs.AnonymousObjectProperty); - break; - case cs.SyntaxKind.ElementAccessExpression: - this.writeElementAccessExpression(expr as cs.ElementAccessExpression); - break; - case cs.SyntaxKind.InvocationExpression: - this.writeInvocationExpression(expr as cs.InvocationExpression); - break; - case cs.SyntaxKind.NewExpression: - this.writeNewExpression(expr as cs.NewExpression); - break; - case cs.SyntaxKind.CastExpression: - this.writeCastExpression(expr as cs.CastExpression); - break; - case cs.SyntaxKind.NonNullExpression: - this.writeNonNullExpression(expr as cs.NonNullExpression); - break; - case cs.SyntaxKind.NullSafeExpression: - this.writeNullSafeExpression(expr as cs.NullSafeExpression); - break; - case cs.SyntaxKind.Identifier: - this.writeIdentifier(expr as cs.Identifier); - break; - case cs.SyntaxKind.ToDoExpression: - this.writeToDoExpression(expr as cs.ToDoExpression); - break; - case cs.SyntaxKind.DefaultExpression: - this.writeDefaultExpression(expr as cs.DefaultExpression); - break; - case cs.SyntaxKind.TypeOfExpression: - this.writeTypeOfExpression(expr as cs.TypeOfExpression); - break; - default: - throw new Error(`Unhandled expression type: ${cs.SyntaxKind[expr.nodeType]}`); - } - } - private writeDefaultExpression(expr: cs.DefaultExpression) { - this.write('default'); - if (expr.type) { - this.write('('); - this.writeType(expr.type); - this.write(')'); - } - } - - private writeTypeOfExpression(expr: cs.TypeOfExpression) { + protected writeTypeOfExpression(expr: cs.TypeOfExpression) { this.write('typeof'); if (expr.expression) { this.write('('); @@ -795,42 +570,21 @@ export default class CSharpAstPrinter { } } - private writePrefixUnaryExpression(expr: cs.PrefixUnaryExpression) { + protected writePrefixUnaryExpression(expr: cs.PrefixUnaryExpression) { this.write(expr.operator); this.writeExpression(expr.operand); } - private writePostfixUnaryExpression(expr: cs.PostfixUnaryExpression) { - this.writeExpression(expr.operand); - this.write(expr.operator); - } - - private writeNullLiteral(expr: cs.NullLiteral) { - this.write('null'); - } - - private writeBooleanLiteral(expr: cs.BooleanLiteral) { - this.write(expr.nodeType === cs.SyntaxKind.TrueLiteral ? 'true' : 'false'); - } - - private writeThisLiteral(expr: cs.ThisLiteral) { - this.write('this'); - } - - private writeBaseLiteralExpression(expr: cs.BaseLiteralExpression) { + protected writeBaseLiteralExpression(expr: cs.BaseLiteralExpression) { this.write('base'); } - private writeStringLiteral(expr: cs.StringLiteral) { - this.write(JSON.stringify(expr.text)); - } - - private writeAwaitExpression(expr: cs.AwaitExpression) { + protected writeAwaitExpression(expr: cs.AwaitExpression) { this.write('await '); this.writeExpression(expr.expression); } - private writeBinaryExpression(expr: cs.BinaryExpression) { + protected writeBinaryExpression(expr: cs.BinaryExpression) { this.writeExpression(expr.left); this.write(' '); this.write(expr.operator); @@ -838,7 +592,7 @@ export default class CSharpAstPrinter { this.writeExpression(expr.right); } - private writeConditionalExpression(expr: cs.ConditionalExpression) { + protected writeConditionalExpression(expr: cs.ConditionalExpression) { this.writeExpression(expr.condition); this.write(' ? '); this.writeExpression(expr.whenTrue); @@ -846,33 +600,27 @@ export default class CSharpAstPrinter { this.writeExpression(expr.whenFalse); } - private writeLambdaExpression(expr: cs.LambdaExpression) { + protected writeLambdaExpression(expr: cs.LambdaExpression) { this.write('('); this.writeCommaSeparated(expr.parameters, p => this.writeParameter(p)); this.write(') => '); - if (expr.body.nodeType === cs.SyntaxKind.Block) { - this.writeBlock(expr.body as cs.Block); + if (cs.isBlock(expr.body)) { + this.writeBlock(expr.body); } else { this.writeExpression(expr.body); } } - private writeNumericLiteral(expr: cs.NumericLiteral) { + protected writeNumericLiteral(expr: cs.NumericLiteral) { this.write(expr.value); } - private writeStringTemplateExpression(expr: cs.StringTemplateExpression) { + protected writeStringTemplateExpression(expr: cs.StringTemplateExpression) { this.write('string.Format(System.Globalization.CultureInfo.InvariantCulture, @"'); let exprs: cs.Expression[] = []; expr.chunks.forEach(c => { - if (c.nodeType === cs.SyntaxKind.StringLiteral) { - const escapedText = (c as cs.StringLiteral).text - .split('"') - .join('""') - .split('\n') - .join('\\n') - .split('\r') - .join('\\r'); + if (cs.isStringLiteral(c)) { + const escapedText = c.text.split('"').join('""'); this.write(escapedText); } else { this.write(`{${exprs.length}}`); @@ -883,23 +631,11 @@ export default class CSharpAstPrinter { exprs.forEach(expr => { this.write(', '); this.writeExpression(expr); - }) - this.write(')'); - } - - private writeIsExpression(expr: cs.IsExpression) { - this.writeExpression(expr.expression); - this.write(' is '); - this.writeType(expr.type); - } - - private writeParenthesizedExpression(expr: cs.ParenthesizedExpression) { - this.write('('); - this.writeExpression(expr.expression); + }); this.write(')'); } - private writeArrayCreationExpression(expr: cs.ArrayCreationExpression) { + protected writeArrayCreationExpression(expr: cs.ArrayCreationExpression) { if (expr.type) { this.write('new '); this.writeType(expr.type, true); @@ -923,8 +659,7 @@ export default class CSharpAstPrinter { this.writeExpression(expr.sizeExpression!); this.write(']'); } - } - else if (expr.values && expr.values.length > 0) { + } else if (expr.values && expr.values.length > 0) { this.write('AlphaTab.Core.TypeHelper.CreateList('); this.writeCommaSeparated(expr.values, v => { if (expr.values!.length > 10) { @@ -938,49 +673,24 @@ export default class CSharpAstPrinter { } } - private writeMemberAccessExpression(expr: cs.MemberAccessExpression) { + protected writeMemberAccessExpression(expr: cs.MemberAccessExpression) { this.writeExpression(expr.expression); this.write(expr.nullSafe ? '?.' : '.'); const name = this._context.getSymbolName(expr) ?? expr.member; this.write(name); } - private writeAnonymousObjectCreationExpression(expr: cs.AnonymousObjectCreationExpression) { - this.write('new'); - this.beginBlock(); - - expr.properties.forEach(p => this.writeAnonymousObjectProperty(p)); - - this.endBlock(); - } - - private writeAnonymousObjectProperty(expr: cs.AnonymousObjectProperty) { - this.write(expr.name); - this.write(' = '); - this.writeExpression(expr.value); - this.writeLine(','); - } - - private writeElementAccessExpression(expr: cs.ElementAccessExpression) { + protected writeElementAccessExpression(expr: cs.ElementAccessExpression) { this.writeExpression(expr.expression); + if (expr.nullSafe) { + this.write('?'); + } this.write('['); this.writeExpression(expr.argumentExpression); this.write(']'); } - private writeInvocationExpression(expr: cs.InvocationExpression) { - this.writeExpression(expr.expression); - if (expr.typeArguments) { - this.write('<'); - this.writeCommaSeparated(expr.typeArguments, t => this.writeType(t)); - this.write('>'); - } - this.write('('); - this.writeCommaSeparated(expr.arguments, a => this.writeExpression(a)); - this.write(')'); - } - - private writeNewExpression(expr: cs.NewExpression) { + protected writeNewExpression(expr: cs.NewExpression) { this.write('new '); this.writeType(expr.type, true); this.write('('); @@ -988,95 +698,21 @@ export default class CSharpAstPrinter { this.write(')'); } - private writeCastExpression(expr: cs.CastExpression) { + protected writeCastExpression(expr: cs.CastExpression) { this.write('('); this.writeType(expr.type); this.write(')'); this.writeExpression(expr.expression); } - private writeNonNullExpression(expr: cs.NonNullExpression) { - this.writeExpression(expr.expression); - this.write('!'); - } - - private writeNullSafeExpression(expr: cs.NullSafeExpression) { + protected writeNonNullExpression(expr: cs.NonNullExpression) { this.writeExpression(expr.expression); - this.write('?'); - } - - private writeIdentifier(expr: cs.Identifier) { - const name = this._context.getSymbolName(expr) ?? expr.text; - this.write(name); - } - - private writeToDoExpression(expr: cs.ToDoExpression) { - this.write('/* TODO */'); - } - - private writeStatement(s: cs.Statement) { - switch (s.nodeType) { - case cs.SyntaxKind.EmptyStatement: - this.writeEmptyStatement(s as cs.EmptyStatement); - break; - case cs.SyntaxKind.Block: - this.writeBlock(s as cs.Block); - break; - case cs.SyntaxKind.VariableStatement: - this.writeVariableStatement(s as cs.VariableStatement); - break; - case cs.SyntaxKind.ExpressionStatement: - this.writeExpressionStatement(s as cs.ExpressionStatement); - break; - case cs.SyntaxKind.IfStatement: - this.writeIfStatement(s as cs.IfStatement); - break; - case cs.SyntaxKind.DoStatement: - this.writeDoStatement(s as cs.DoStatement); - break; - case cs.SyntaxKind.WhileStatement: - this.writeWhileStatement(s as cs.WhileStatement); - break; - case cs.SyntaxKind.ForStatement: - this.writeForStatement(s as cs.ForStatement); - break; - case cs.SyntaxKind.ForEachStatement: - this.writeForEachStatement(s as cs.ForEachStatement); - break; - case cs.SyntaxKind.BreakStatement: - this.writeBreakStatement(s as cs.BreakStatement); - break; - case cs.SyntaxKind.ContinueStatement: - this.writeContinueStatement(s as cs.ContinueStatement); - break; - case cs.SyntaxKind.ReturnStatement: - this.writeReturnStatement(s as cs.ReturnStatement); - break; - case cs.SyntaxKind.SwitchStatement: - this.writeSwitchStatement(s as cs.SwitchStatement); - break; - case cs.SyntaxKind.ThrowStatement: - this.writeThrowStatement(s as cs.ThrowStatement); - break; - case cs.SyntaxKind.TryStatement: - this.writeTryStatement(s as cs.TryStatement); - break; - } - } - - private writeTryStatement(s: cs.TryStatement) { - this.writeLine('try'); - this.writeBlock(s.tryBlock); - if (s.catchClauses) { - s.catchClauses.forEach(c => this.writeCatchClause(c)); - } - if (s.finallyBlock) { - this.writeLine('finally'); - this.writeBlock(s.finallyBlock); + if (!cs.isNonNullExpression(expr)) { + this.write('!'); } } - private writeCatchClause(c: cs.CatchClause): void { + protected writeCatchClause(c: cs.CatchClause): void { this.write('catch ('); this.writeType(c.variableDeclaration.type); this.write(' '); @@ -1085,33 +721,24 @@ export default class CSharpAstPrinter { this.writeBlock(c.block); } - private writeThrowStatement(s: cs.ThrowStatement) { - this.write('throw'); - if (s.expression) { - this.write(' '); - this.writeExpression(s.expression); - } - this.writeLine(';'); - } - - private writeSwitchStatement(s: cs.SwitchStatement) { + protected writeSwitchStatement(s: cs.SwitchStatement) { this.write('switch ('); this.writeExpression(s.expression); this.writeLine(')'); this.beginBlock(); s.caseClauses.forEach(c => { - if (c.nodeType === cs.SyntaxKind.DefaultClause) { - this.writeDefaultClause(c as cs.DefaultClause); - } else { - this.writeCaseClause(c as cs.CaseClause); + if (cs.isDefaultClause(c)) { + this.writeDefaultClause(c); + } else if (cs.isCaseClause(c)) { + this.writeCaseClause(c); } }); this.endBlock(); } - private writeCaseClause(c: cs.CaseClause) { + protected writeCaseClause(c: cs.CaseClause) { this.write('case '); this.writeExpression(c.expression); this.writeLine(':'); @@ -1120,34 +747,17 @@ export default class CSharpAstPrinter { this._indent--; } - private writeDefaultClause(c: cs.DefaultClause) { + protected writeDefaultClause(c: cs.DefaultClause) { this.writeLine('default:'); this._indent++; c.statements.forEach(s => this.writeStatement(s)); this._indent--; } - private writeReturnStatement(r: cs.ReturnStatement) { - this.write('return'); - if (r.expression) { - this.write(' '); - this.writeExpression(r.expression); - } - this.writeLine(';'); - } - - private writeContinueStatement(_: cs.ContinueStatement) { - this.writeLine('continue;'); - } - - private writeBreakStatement(_: cs.BreakStatement) { - this.writeLine('break;'); - } - - private writeForEachStatement(s: cs.ForEachStatement) { + protected writeForEachStatement(s: cs.ForEachStatement) { this.write('foreach ('); - if (s.initializer.nodeType === cs.SyntaxKind.VariableDeclarationList) { - this.writeVariableDeclarationList(s.initializer as cs.VariableDeclarationList); + if (cs.isVariableDeclarationList(s.initializer)) { + this.writeVariableDeclarationList(s.initializer); } else { this.writeExpression(s.initializer as cs.Expression); } @@ -1155,7 +765,7 @@ export default class CSharpAstPrinter { this.writeExpression(s.expression); this.writeLine(')'); - if (s.statement.nodeType === cs.SyntaxKind.Block) { + if (cs.isBlock(s.statement)) { this.writeStatement(s.statement); } else { this._indent++; @@ -1164,11 +774,11 @@ export default class CSharpAstPrinter { } } - private writeForStatement(s: cs.ForStatement) { + protected writeForStatement(s: cs.ForStatement) { this.write('for ('); if (s.initializer) { - if (s.initializer.nodeType === cs.SyntaxKind.VariableDeclarationList) { - this.writeVariableDeclarationList(s.initializer as cs.VariableDeclarationList); + if (cs.isVariableDeclarationList(s.initializer)) { + this.writeVariableDeclarationList(s.initializer); } else { this.writeExpression(s.initializer as cs.Expression); } @@ -1185,20 +795,7 @@ export default class CSharpAstPrinter { } this.writeLine(')'); - if (s.statement.nodeType === cs.SyntaxKind.Block) { - this.writeStatement(s.statement); - } else { - this._indent++; - this.writeStatement(s.statement); - this._indent--; - } - } - - private writeWhileStatement(s: cs.WhileStatement) { - this.write('while ('); - this.writeExpression(s.expression); - this.writeLine(')'); - if (s.statement.nodeType === cs.SyntaxKind.Block) { + if (cs.isBlock(s.statement)) { this.writeStatement(s.statement); } else { this._indent++; @@ -1207,52 +804,7 @@ export default class CSharpAstPrinter { } } - private writeDoStatement(s: cs.DoStatement) { - this.writeLine('do'); - this.writeStatement(s.statement); - this.write('while ('); - this.writeExpression(s.expression); - this.writeLine(');'); - } - - private writeIfStatement(s: cs.IfStatement) { - this.write('if ('); - this.writeExpression(s.expression); - this.writeLine(')'); - if (s.thenStatement.nodeType === cs.SyntaxKind.Block) { - this.writeStatement(s.thenStatement); - } else { - this._indent++; - this.writeStatement(s.thenStatement); - this._indent--; - } - - if (s.elseStatement) { - this.write('else '); - if (s.elseStatement.nodeType === cs.SyntaxKind.IfStatement) { - this.writeStatement(s.elseStatement); - } else if (s.elseStatement.nodeType === cs.SyntaxKind.Block) { - this.writeLine(); - this.writeStatement(s.elseStatement); - } else { - this.writeLine(); - this._indent++; - this.writeStatement(s.elseStatement); - this._indent--; - } - } - } - private writeExpressionStatement(s: cs.ExpressionStatement) { - this.writeExpression(s.expression); - this.writeLine(';'); - } - - private writeVariableStatement(v: cs.VariableStatement) { - this.writeVariableDeclarationList(v.declarationList); - this.writeLine(';'); - } - - private writeVariableDeclarationList(declarationList: cs.VariableDeclarationList) { + protected writeVariableDeclarationList(declarationList: cs.VariableDeclarationList) { this.writeType(declarationList.declarations[0].type); declarationList.declarations.forEach((d, i) => { @@ -1269,7 +821,7 @@ export default class CSharpAstPrinter { this.write(', '); } this.write(v); - }) + }); this.write(')'); } else { this.write(d.name); @@ -1282,70 +834,13 @@ export default class CSharpAstPrinter { }); } - private writeEmptyStatement(_: cs.EmptyStatement) { - this.writeLine(';'); - } - - private writeBlock(b: cs.Block) { + protected writeBlock(b: cs.Block) { this.beginBlock(); b.statements.forEach(s => this.writeStatement(s)); this.endBlock(); } - private writeVisibility(visibility: cs.Visibility) { - switch (visibility) { - case cs.Visibility.Public: - this.write('public '); - break; - case cs.Visibility.Private: - this.write('private '); - break; - case cs.Visibility.Protected: - this.write('protected '); - break; - case cs.Visibility.Internal: - this.write('internal '); - break; - } - } - - private writeUsing(using: cs.UsingDeclaration) { - if (using.typeAlias) { - this.writeLine(`using ${using.typeAlias} = ${using.namespaceOrTypeName};`); - } else { - this.writeLine(`using ${using.namespaceOrTypeName};`); - } - } - - private writeLine(txt?: string) { - this.writeIndent(); - if (txt) { - this.write(txt); - } - this.write(ts.sys.newLine); - this._isStartOfLine = true; - } - - private write(txt: string) { - this.writeIndent(); - fs.writeSync(this._fileHandle, txt); - this._isStartOfLine = false; - } - - private writeIndent() { - if (this._isStartOfLine && this._indent > 0) { - fs.writeSync(this._fileHandle, this._indent === 1 ? ' ' : ' '.repeat(this._indent)); - this._isStartOfLine = false; - } - } - - private beginBlock() { - this.writeLine('{'); - this._indent++; - } - - private endBlock() { - this._indent--; - this.writeLine('}'); + protected writeUsing(using: cs.UsingDeclaration) { + this.writeLine(`using ${using.namespaceOrTypeName};`); } } diff --git a/src.compiler/csharp/CSharpAstTransformer.ts b/src.compiler/csharp/CSharpAstTransformer.ts index e7d18a3ea..c1efed9ed 100644 --- a/src.compiler/csharp/CSharpAstTransformer.ts +++ b/src.compiler/csharp/CSharpAstTransformer.ts @@ -4,10 +4,18 @@ import * as path from 'path'; import CSharpEmitterContext from './CSharpEmitterContext'; export default class CSharpAstTransformer { - private _typeScriptFile: ts.SourceFile; - private _csharpFile: cs.SourceFile; - private _context: CSharpEmitterContext; - private _declarationOrAssignmentTypeStack: ts.Type[] = []; + protected _typeScriptFile: ts.SourceFile; + protected _csharpFile: cs.SourceFile; + protected _context: CSharpEmitterContext; + protected _currentClassElement: ts.ClassElement | null = null; + protected _declarationOrAssignmentTypeStack: ts.Type[] = []; + + protected _testClassAttribute: string = 'microsoft.visualStudio.testTools.unitTesting.TestClass'; + protected _testMethodAttribute: string = 'microsoft.visualStudio.testTools.unitTesting.TestMethod'; + + public get extension(): string { + return '.cs'; + } public constructor(typeScript: ts.SourceFile, context: CSharpEmitterContext) { this._typeScriptFile = typeScript; @@ -17,33 +25,33 @@ export default class CSharpAstTransformer { path.resolve(this._context.compilerOptions.baseUrl!), path.resolve(this._typeScriptFile.fileName) ); - fileName = path.join(context.compilerOptions.outDir!, this.removeExtension(fileName) + '.cs'); + fileName = this.buildFileName(fileName, context); this._csharpFile = { parent: null, tsNode: this._typeScriptFile, nodeType: cs.SyntaxKind.SourceFile, fileName: fileName, - usings: [ - { - namespaceOrTypeName: 'System', + usings: this._context.getDefaultUsings().map(u => { + return { + namespaceOrTypeName: u, nodeType: cs.SyntaxKind.UsingDeclaration - } as cs.UsingDeclaration, - { - namespaceOrTypeName: 'AlphaTab.Core', - nodeType: cs.SyntaxKind.UsingDeclaration - } as cs.UsingDeclaration - ], + } as cs.UsingDeclaration; + }), namespace: { parent: null, nodeType: cs.SyntaxKind.NamespaceDeclaration, - namespace: 'AlphaTab', + namespace: this._context.toPascalCase('alphaTab'), declarations: [] } }; this._csharpFile.namespace.parent = this._csharpFile; } + protected buildFileName(fileName: string, context: CSharpEmitterContext): string { + return path.join(context.compilerOptions.outDir!, this.removeExtension(fileName) + this.extension); + } + public transform() { // if the default export is a class: // - global statements will be put into the static constructor of the class @@ -133,11 +141,27 @@ export default class CSharpAstTransformer { globalExports.forEach(x => { if (!x.name && x.exportClause) { if (ts.isNamespaceExport(x.exportClause)) { - this._context.addTsNodeDiagnostics( - x.exportClause, - 'Namespace exports are not yet supported', - ts.DiagnosticCategory.Error - ); + if (!x.moduleSpecifier) { + this._context.addTsNodeDiagnostics( + x.exportClause, + 'Failed to export namespace, missing module specifier', + ts.DiagnosticCategory.Error + ); + } else { + const module = this._context.typeChecker.getSymbolAtLocation(x.moduleSpecifier); + if (!module) { + this._context.addTsNodeDiagnostics( + x.exportClause, + 'Failed to export namespace, cannot resolve module', + ts.DiagnosticCategory.Error + ); + } else { + const exports = this._context.typeChecker.getExportsOfModule(module); + for (const exp of exports) { + this._context.registerSymbolAsExported(exp); + } + } + } } else { x.exportClause.elements.forEach(e => { const symbol = this._context.typeChecker.getTypeAtLocation(e.name)?.symbol; @@ -153,17 +177,12 @@ export default class CSharpAstTransformer { }); } } else { - this._context.addTsNodeDiagnostics( - x, - 'Unsupported export', - ts.DiagnosticCategory.Error - ); + this._context.addTsNodeDiagnostics(x, 'Unsupported export', ts.DiagnosticCategory.Error); } }); globalStatements.forEach(s => { - if (ts.isVariableStatement(s) - && s.modifiers?.find(m => m.kind === ts.SyntaxKind.ExportKeyword)) { + if (ts.isVariableStatement(s) && s.modifiers?.find(m => m.kind === ts.SyntaxKind.ExportKeyword)) { s.declarationList.declarations.forEach(d => { if (d.initializer && ts.isObjectLiteralExpression(d.initializer)) { d.initializer.properties.forEach(p => { @@ -186,18 +205,12 @@ export default class CSharpAstTransformer { ); } }); + } else { + this._context.addTsNodeDiagnostics(d, 'Unsupported export', ts.DiagnosticCategory.Message); } - else { - this._context.addTsNodeDiagnostics( - d, - 'Unsupported export', - ts.DiagnosticCategory.Message - ); - } - }) - + }); } - }) + }); // TODO: register global exports } else { @@ -241,7 +254,7 @@ export default class CSharpAstTransformer { folders.shift(); } this._csharpFile.namespace.namespace = - 'AlphaTab' + folders.map(f => '.' + f.substr(0, 1).toUpperCase() + f.substr(1)).join(''); + this._context.toPascalCase('alphaTab') + folders.map(f => '.' + this._context.toPascalCase(f)).join(''); if (defaultExport) { this.visit( @@ -261,7 +274,7 @@ export default class CSharpAstTransformer { } } - private isDefaultExport(s: ts.NamedDeclaration): boolean { + protected isDefaultExport(s: ts.NamedDeclaration): boolean { const isDefaultExport = s.modifiers && !!s.modifiers.find(m => m.kind === ts.SyntaxKind.DefaultKeyword); if (isDefaultExport) { return true; @@ -276,16 +289,12 @@ export default class CSharpAstTransformer { return false; } - private visit( + protected visit( node: ts.Node, additionalNestedExportDeclarations?: ts.Declaration[], additionalNestedNonExportsDeclarations?: ts.Declaration[], globalStatements?: ts.Statement[] ): ts.Node { - if (this.shouldSkip(node, false)) { - return node; - } - if (ts.isClassDeclaration(node)) { this.visitClassDeclaration( node, @@ -297,31 +306,36 @@ export default class CSharpAstTransformer { this.visitEnumDeclaration(node); } else if (ts.isInterfaceDeclaration(node)) { this.visitInterfaceDeclaration(node); - } else if (ts.isTypeAliasDeclaration(node) && ts.isFunctionTypeNode(node.type)) { - this.visitTypeAliasDeclaration(node); } return node; } - private shouldSkip(node: ts.Node, checkComments: boolean) { + protected shouldSkip(node: ts.Node, checkComments: boolean) { if (checkComments) { const text = node.getSourceFile().text; // check for /*@target web*/ marker - const commentText = text.substr(node.getStart() - node.getLeadingTriviaWidth(), node.getLeadingTriviaWidth()); + const commentText = text.substr( + node.getStart() - node.getLeadingTriviaWidth(), + node.getLeadingTriviaWidth() + ); if (commentText.indexOf('/*@target web*/') >= 0) { return true; } } const tags = ts.getJSDocTags(node).filter(t => t.tagName.text === 'target'); if (tags.length > 0) { - return !tags.find(t => t.comment === 'csharp'); + return !tags.find(t => t.comment === this.targetTag); } return false; } - private visitEnumDeclaration(node: ts.EnumDeclaration) { + public get targetTag(): string { + return 'csharp'; + } + + protected visitEnumDeclaration(node: ts.EnumDeclaration) { const csEnum: cs.EnumDeclaration = { visibility: cs.Visibility.Public, name: node.name.text, @@ -331,7 +345,8 @@ export default class CSharpAstTransformer { tsNode: node, partial: false, skipEmit: this.shouldSkip(node, false), - tsSymbol: this._context.getSymbolForDeclaration(node) + tsSymbol: this._context.getSymbolForDeclaration(node), + hasVirtualMembersOrSubClasses: false }; if (node.name) { @@ -344,7 +359,7 @@ export default class CSharpAstTransformer { this._context.registerSymbol(csEnum); } - private visitEnumMember(parent: cs.EnumDeclaration, enumMember: ts.EnumMember) { + protected visitEnumMember(parent: cs.EnumDeclaration, enumMember: ts.EnumMember) { const csEnumMember: cs.EnumMember = { parent: parent, tsNode: enumMember, @@ -365,11 +380,7 @@ export default class CSharpAstTransformer { this._context.registerSymbol(csEnumMember); } - private visitTypeAliasDeclaration(node: ts.TypeAliasDeclaration) { - //throw new Error("Method not implemented."); - } - - private visitInterfaceDeclaration(node: ts.InterfaceDeclaration) { + protected visitInterfaceDeclaration(node: ts.InterfaceDeclaration) { let extendsClauses: ts.ExpressionWithTypeArguments[] = []; node.heritageClauses?.forEach(c => { @@ -387,7 +398,8 @@ export default class CSharpAstTransformer { tsNode: node, skipEmit: this.shouldSkip(node, false), partial: !!ts.getJSDocTags(node).find(t => t.tagName.text === 'partial'), - tsSymbol: this._context.getSymbolForDeclaration(node) + tsSymbol: this._context.getSymbolForDeclaration(node), + hasVirtualMembersOrSubClasses: false }; if (node.name) { @@ -413,13 +425,18 @@ export default class CSharpAstTransformer { }); } - node.members.forEach(m => this.visitInterfaceElement(csInterface, m)); + if (!csInterface.skipEmit) { + node.members.forEach(m => this.visitInterfaceElement(csInterface, m)); + } this._csharpFile.namespace.declarations.push(csInterface); this._context.registerSymbol(csInterface); } - private visitTypeParameterDeclaration(parent: cs.Node, p: ts.TypeParameterDeclaration): cs.TypeParameterDeclaration { + protected visitTypeParameterDeclaration( + parent: cs.Node, + p: ts.TypeParameterDeclaration + ): cs.TypeParameterDeclaration { const csTypeParameter: cs.TypeParameterDeclaration = { nodeType: cs.SyntaxKind.TypeParameterDeclaration, name: p.name.text, @@ -428,14 +445,14 @@ export default class CSharpAstTransformer { }; if (p.constraint) { - let constraintType = (ts.isUnionTypeNode(p.constraint) ? p.constraint.types[0] : p.constraint); + let constraintType = ts.isUnionTypeNode(p.constraint) ? p.constraint.types[0] : p.constraint; csTypeParameter.constraint = this.createUnresolvedTypeNode(csTypeParameter, constraintType); } return csTypeParameter; } - private createUnresolvedTypeNode( + protected createUnresolvedTypeNode( parent: cs.Node | null, tsNode: ts.Node, tsType?: ts.Type, @@ -454,7 +471,7 @@ export default class CSharpAstTransformer { } as cs.UnresolvedTypeNode; let typeArguments = (tsType as ts.TypeReference)?.typeArguments; - if(tsType && !typeArguments) { + if (tsType && !typeArguments) { const nonNullable = this._context.typeChecker.getNonNullableType(tsType); typeArguments = (nonNullable as ts.TypeReference)?.typeArguments; } @@ -466,10 +483,7 @@ export default class CSharpAstTransformer { return unresolved; } - private createVarTypeNode( - parent: cs.Node | null, - tsNode: ts.Node, - ): cs.PrimitiveTypeNode { + protected createVarTypeNode(parent: cs.Node | null, tsNode: ts.Node): cs.PrimitiveTypeNode { const varNode = { nodeType: cs.SyntaxKind.PrimitiveTypeNode, tsNode: tsNode, @@ -488,20 +502,23 @@ export default class CSharpAstTransformer { parent: this._csharpFile.namespace, isAbstract: false, partial: false, - members: [] + members: [], + hasVirtualMembersOrSubClasses: false }; - csClass.attributes = [ - { - parent: csClass, - nodeType: cs.SyntaxKind.Attribute, - type: { - parent: null, - nodeType: cs.SyntaxKind.TypeReference, - reference: 'Microsoft.VisualStudio.TestTools.UnitTesting.TestClass' - } as cs.TypeReference - } - ]; + if (this._testClassAttribute.length > 0) { + csClass.attributes = [ + { + parent: csClass, + nodeType: cs.SyntaxKind.Attribute, + type: { + parent: null, + nodeType: cs.SyntaxKind.TypeReference, + reference: this._context.makeTypeName(this._testClassAttribute) + } as cs.TypeReference + } + ]; + } ((d.arguments![1] as ts.ArrowFunction).body as ts.Block).statements.forEach(s => { if (ts.isExpressionStatement(s)) { @@ -538,7 +555,7 @@ export default class CSharpAstTransformer { this._csharpFile.namespace.declarations.push(csClass); } - private visitTestClassMethod(parent: cs.ClassDeclaration, d: ts.FunctionDeclaration) { + protected visitTestClassMethod(parent: cs.ClassDeclaration, d: ts.FunctionDeclaration) { const signature = this._context.typeChecker.getSignatureFromDeclaration(d); const returnType = this._context.typeChecker.getReturnTypeOfSignature(signature!); @@ -549,16 +566,15 @@ export default class CSharpAstTransformer { isOverride: false, isStatic: false, isVirtual: false, + partial: !!ts.getJSDocTags(d).find(t => t.tagName.text === 'partial'), name: this._context.toPascalCase((d.name as ts.Identifier).text), parameters: [], returnType: this.createUnresolvedTypeNode(null, d.type ?? d, returnType), - visibility: this.mapVisibility(d.modifiers), + visibility: this.mapVisibility(d), tsNode: d, skipEmit: this.shouldSkip(d, true) }; - csMethod.isAsync = - !!d.modifiers && - !!d.modifiers.find(m => m.kind === ts.SyntaxKind.AsyncKeyword); + csMethod.isAsync = !!d.modifiers && !!d.modifiers.find(m => m.kind === ts.SyntaxKind.AsyncKeyword); const type = this._context.typeChecker.getTypeAtLocation(d.name!); csMethod.returnType.parent = csMethod; @@ -572,7 +588,7 @@ export default class CSharpAstTransformer { this._context.registerSymbol(csMethod); } - private visitTestMethod(parent: cs.ClassDeclaration, d: ts.CallExpression) { + protected visitTestMethod(parent: cs.ClassDeclaration, d: ts.CallExpression) { const csMethod: cs.MethodDeclaration = { parent: parent, nodeType: cs.SyntaxKind.MethodDeclaration, @@ -580,7 +596,8 @@ export default class CSharpAstTransformer { isOverride: false, isStatic: false, isVirtual: false, - name: this._context.toPascalCase((d.arguments[0] as ts.StringLiteral).text), + partial: !!ts.getJSDocTags(d).find(t => t.tagName.text === 'partial'), + name: this._context.toMethodName((d.arguments[0] as ts.StringLiteral).text), parameters: [], returnType: { parent: null, @@ -604,7 +621,7 @@ export default class CSharpAstTransformer { type: { parent: null, nodeType: cs.SyntaxKind.TypeReference, - reference: 'Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod' + reference: this._context.makeTypeName(this._testMethodAttribute) } as cs.TypeReference } ]; @@ -618,7 +635,7 @@ export default class CSharpAstTransformer { parent.members.push(csMethod); } - private visitTestClassProperty(parent: cs.ClassDeclaration, s: ts.VariableStatement) { + protected visitTestClassProperty(parent: cs.ClassDeclaration, s: ts.VariableStatement) { s.declarationList.declarations.forEach(d => { const type = this._context.typeChecker.getTypeAtLocation(d.name); if (this._context.isFunctionType(type) && d.initializer && ts.isArrowFunction(d.initializer)) { @@ -629,6 +646,7 @@ export default class CSharpAstTransformer { isOverride: false, isStatic: false, isVirtual: false, + partial: !!ts.getJSDocTags(d).find(t => t.tagName.text === 'partial'), name: this._context.toPascalCase(d.name.getText()), returnType: {} as cs.TypeNode, visibility: cs.Visibility.Private, @@ -639,7 +657,7 @@ export default class CSharpAstTransformer { !!d.initializer.modifiers && !!d.initializer.modifiers.find(m => m.kind === ts.SyntaxKind.AsyncKeyword); - const functionType = type.symbol.declarations.find(d => + const functionType = type.symbol.declarations!.find(d => ts.isFunctionTypeNode(d) ) as ts.FunctionTypeNode; @@ -696,7 +714,7 @@ export default class CSharpAstTransformer { }); } - private visitClassDeclaration( + protected visitClassDeclaration( node: ts.ClassDeclaration, additionalNestedExportDeclarations?: ts.Declaration[], additionalNestedNonExportsDeclarations?: ts.Declaration[], @@ -724,7 +742,8 @@ export default class CSharpAstTransformer { partial: !!ts.getJSDocTags(node).find(t => t.tagName.text === 'partial'), members: [], skipEmit: this.shouldSkip(node, false), - tsSymbol: this._context.getSymbolForDeclaration(node) + tsSymbol: this._context.getSymbolForDeclaration(node), + hasVirtualMembersOrSubClasses: false }; if (node.name) { @@ -759,39 +778,41 @@ export default class CSharpAstTransformer { }); } - node.members.forEach(m => this.visitClassElement(csClass, m)); + if (!csClass.skipEmit) { + node.members.forEach(m => this.visitClassElement(csClass, m)); - if (globalStatements && globalStatements.length > 0) { - const staticConstructor = { - parent: csClass, - isStatic: true, - name: 'cctor', - nodeType: cs.SyntaxKind.ConstructorDeclaration, - parameters: [], - visibility: cs.Visibility.None, - tsNode: node, - body: { - parent: null, - nodeType: cs.SyntaxKind.Block, - statements: [] - } as cs.Block - } as cs.ConstructorDeclaration; + if (globalStatements && globalStatements.length > 0) { + const staticConstructor = { + parent: csClass, + isStatic: true, + name: 'cctor', + nodeType: cs.SyntaxKind.ConstructorDeclaration, + parameters: [], + visibility: cs.Visibility.None, + tsNode: node, + body: { + parent: null, + nodeType: cs.SyntaxKind.Block, + statements: [] + } as cs.Block + } as cs.ConstructorDeclaration; - globalStatements.forEach(s => { - const st = this.visitStatement(staticConstructor.body!, s)!; - if (st) { - (staticConstructor.body as cs.Block).statements.push(st); - } - }); + globalStatements.forEach(s => { + const st = this.visitStatement(staticConstructor.body!, s)!; + if (st) { + (staticConstructor.body as cs.Block).statements.push(st); + } + }); - csClass.members.push(staticConstructor); + csClass.members.push(staticConstructor); + } } this._csharpFile.namespace.declarations.push(csClass); this._context.registerSymbol(csClass); } - private visitDocumentation(node: ts.Node): string | undefined { + protected visitDocumentation(node: ts.Node): string | undefined { let symbol = this._context.typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; @@ -842,7 +863,14 @@ export default class CSharpAstTransformer { return s; } - private visitClassElement(parent: cs.ClassDeclaration, classElement: ts.ClassElement) { + protected visitClassElement(parent: cs.ClassDeclaration, classElement: ts.ClassElement) { + let isSkipped = this.shouldSkip(classElement, false); + if (isSkipped) { + this._context.processingSkippedElement = true; + } + + this._currentClassElement = classElement; + if (ts.isConstructorDeclaration(classElement)) { this.visitConstructorDeclaration(parent, classElement); } else if (ts.isMethodSignature(classElement)) { @@ -864,9 +892,15 @@ export default class CSharpAstTransformer { ts.DiagnosticCategory.Error ); } + + this._currentClassElement = null; + + if (isSkipped) { + this._context.processingSkippedElement = false; + } } - private visitInterfaceElement(parent: cs.InterfaceDeclaration, classElement: ts.TypeElement) { + protected visitInterfaceElement(parent: cs.InterfaceDeclaration, classElement: ts.TypeElement) { if (ts.isMethodSignature(classElement)) { this.visitMethodSignature(parent, classElement); } else if (ts.isPropertySignature(classElement)) { @@ -880,7 +914,7 @@ export default class CSharpAstTransformer { } } - private visitPropertySignature( + protected visitPropertySignature( parent: cs.ClassDeclaration | cs.InterfaceDeclaration, classElement: ts.PropertySignature ) { @@ -932,18 +966,21 @@ export default class CSharpAstTransformer { this._context.registerSymbol(csProperty); } - private visitGetAccessor(parent: cs.ClassDeclaration, classElement: ts.GetAccessorDeclaration) { + protected visitGetAccessor(parent: cs.ClassDeclaration, classElement: ts.GetAccessorDeclaration) { const propertyName = this._context.toPascalCase(classElement.name.getText()); const member = parent.members.find(m => m.name === propertyName); - if (member && member.nodeType === cs.SyntaxKind.PropertyDeclaration) { - let existingProperty = member as cs.PropertyDeclaration; - existingProperty.getAccessor = { + if (member && cs.isPropertyDeclaration(member)) { + member.getAccessor = { keyword: 'get', - parent: existingProperty, + parent: member, nodeType: cs.SyntaxKind.PropertyAccessorDeclaration, tsNode: classElement, - body: classElement.body ? this.visitBlock(existingProperty, classElement.body) : null + body: classElement.body ? this.visitBlock(member, classElement.body) : null } as cs.PropertyAccessorDeclaration; + + if (this._context.markOverride(classElement)) { + member.isOverride = true; + } } else { const signature = this._context.typeChecker.getSignatureFromDeclaration(classElement); const returnType = this._context.typeChecker.getReturnTypeOfSignature(signature!); @@ -956,19 +993,15 @@ export default class CSharpAstTransformer { name: propertyName, nodeType: cs.SyntaxKind.PropertyDeclaration, parent: parent, - visibility: this.mapVisibility(classElement.modifiers), + visibility: this.mapVisibility(classElement), type: this.createUnresolvedTypeNode(null, classElement.type ?? classElement, returnType), - skipEmit: this.shouldSkip(classElement, false) + skipEmit: this.shouldSkip(classElement, false), + tsNode: classElement, + tsSymbol: this._context.getSymbolForDeclaration(classElement) }; - if (newProperty.visibility === cs.Visibility.Public || newProperty.visibility === cs.Visibility.Protected) { - if (this._context.isOverride(classElement)) { - newProperty.isVirtual = false; - newProperty.isOverride = true; - } else { - newProperty.isVirtual = true; - newProperty.isOverride = false; - } + if (this._context.markOverride(classElement)) { + newProperty.isOverride = true; } if (classElement.modifiers) { @@ -1003,18 +1036,23 @@ export default class CSharpAstTransformer { } } - private visitSetAccessor(parent: cs.ClassDeclaration, classElement: ts.SetAccessorDeclaration) { + protected visitSetAccessor(parent: cs.ClassDeclaration, classElement: ts.SetAccessorDeclaration) { const propertyName = this._context.toPascalCase(classElement.name.getText()); const member = parent.members.find(m => m.name === propertyName); - if (member && member.nodeType === cs.SyntaxKind.PropertyDeclaration) { - let existingProperty = member as cs.PropertyDeclaration; - existingProperty.setAccessor = { + if (member && cs.isPropertyDeclaration(member)) { + member.setAccessor = { keyword: 'set', - parent: existingProperty, + parent: member, nodeType: cs.SyntaxKind.PropertyAccessorDeclaration, tsNode: classElement, - body: classElement.body ? this.visitBlock(existingProperty, classElement.body) : null + body: classElement.body ? this.visitBlock(member, classElement.body) : null } as cs.PropertyAccessorDeclaration; + + if (this._context.markOverride(classElement)) { + member.isOverride = true; + } + + return member.setAccessor; } else { const signature = this._context.typeChecker.getSignatureFromDeclaration(classElement); const returnType = this._context.typeChecker.getReturnTypeOfSignature(signature!); @@ -1027,19 +1065,15 @@ export default class CSharpAstTransformer { name: propertyName, nodeType: cs.SyntaxKind.PropertyDeclaration, parent: parent, - visibility: this.mapVisibility(classElement.modifiers), + visibility: this.mapVisibility(classElement), type: this.createUnresolvedTypeNode(null, classElement.type ?? classElement, returnType), - skipEmit: this.shouldSkip(classElement, false) + skipEmit: this.shouldSkip(classElement, false), + tsNode: classElement, + tsSymbol: this._context.getSymbolForDeclaration(classElement) }; - if (newProperty.visibility === cs.Visibility.Public || newProperty.visibility === cs.Visibility.Protected) { - if (this._context.isOverride(classElement)) { - newProperty.isVirtual = false; - newProperty.isOverride = true; - } else { - newProperty.isVirtual = true; - newProperty.isOverride = false; - } + if (this._context.markOverride(classElement)) { + newProperty.isOverride = true; } if (classElement.modifiers) { @@ -1071,14 +1105,16 @@ export default class CSharpAstTransformer { } as cs.PropertyAccessorDeclaration; parent.members.push(newProperty); + + return newProperty.setAccessor; } } - private visitPropertyDeclaration( + protected visitPropertyDeclaration( parent: cs.ClassDeclaration | cs.InterfaceDeclaration, classElement: ts.PropertyDeclaration ) { - const visibility = this.mapVisibility(classElement.modifiers); + const visibility = this.mapVisibility(classElement); const type = this._context.typeChecker.getTypeAtLocation(classElement); const csProperty: cs.PropertyDeclaration = { parent: parent, @@ -1091,31 +1127,26 @@ export default class CSharpAstTransformer { type: this.createUnresolvedTypeNode(null, classElement.type ?? classElement, type), visibility: visibility, tsNode: classElement, + tsSymbol: this._context.getSymbolForDeclaration(classElement), skipEmit: this.shouldSkip(classElement, false) }; - if (csProperty.visibility === cs.Visibility.Public || csProperty.visibility === cs.Visibility.Protected) { - if (this._context.isOverride(classElement)) { - csProperty.isVirtual = false; - csProperty.isOverride = true; - } else { - csProperty.isVirtual = true; - csProperty.isOverride = false; - } - } - if (classElement.name) { csProperty.documentation = this.visitDocumentation(classElement.name); } + if (this._context.markOverride(classElement)) { + csProperty.isOverride = true; + } + let isReadonly = false; if (classElement.modifiers) { classElement.modifiers.forEach(m => { switch (m.kind) { case ts.SyntaxKind.AbstractKeyword: csProperty.isAbstract = true; - if (parent.nodeType === cs.SyntaxKind.ClassDeclaration) { - (parent as cs.ClassDeclaration).isAbstract = true; + if (cs.isClassDeclaration(parent)) { + parent.isAbstract = true; } csProperty.isVirtual = false; csProperty.isOverride = false; @@ -1170,7 +1201,7 @@ export default class CSharpAstTransformer { this._context.registerSymbol(csProperty); } - private visitMethodDeclaration( + protected visitMethodDeclaration( parent: cs.ClassDeclaration | cs.InterfaceDeclaration, classElement: ts.MethodDeclaration ) { @@ -1186,11 +1217,13 @@ export default class CSharpAstTransformer { isOverride: false, isStatic: false, isVirtual: false, - name: this._context.toPascalCase((classElement.name as ts.Identifier).text), + partial: !!ts.getJSDocTags(classElement).find(t => t.tagName.text === 'partial'), + name: this._context.toMethodName((classElement.name as ts.Identifier).text), parameters: [], returnType: this.createUnresolvedTypeNode(null, classElement.type ?? classElement, returnType), - visibility: this.mapVisibility(classElement.modifiers), + visibility: this.mapVisibility(classElement), tsNode: classElement, + tsSymbol: this._context.getSymbolForDeclaration(classElement), skipEmit: this.shouldSkip(classElement, false) }; @@ -1198,14 +1231,8 @@ export default class CSharpAstTransformer { csMethod.documentation = this.visitDocumentation(classElement.name); } - if (csMethod.visibility === cs.Visibility.Public || csMethod.visibility === cs.Visibility.Protected) { - if (this._context.isOverride(classElement)) { - csMethod.isVirtual = false; - csMethod.isOverride = true; - } else { - csMethod.isVirtual = true; - csMethod.isOverride = false; - } + if (this._context.markOverride(classElement)) { + csMethod.isOverride = true; } if (classElement.modifiers) { @@ -1213,11 +1240,10 @@ export default class CSharpAstTransformer { switch (m.kind) { case ts.SyntaxKind.AbstractKeyword: csMethod.isAbstract = true; - if (parent.nodeType === cs.SyntaxKind.ClassDeclaration) { - (parent as cs.ClassDeclaration).isAbstract = true; + if (cs.isClassDeclaration(parent)) { + parent.isAbstract = true; } csMethod.isVirtual = false; - csMethod.isOverride = false; break; case ts.SyntaxKind.StaticKeyword: csMethod.isStatic = true; @@ -1243,18 +1269,18 @@ export default class CSharpAstTransformer { classElement.parameters.forEach(p => this.visitMethodParameter(csMethod, p)); - if (classElement.body) { + if (classElement.body && !csMethod.skipEmit) { csMethod.body = this.visitBlock(csMethod, classElement.body); } switch (csMethod.name) { - case 'ToString': + case this._context.toMethodName('toString'): if (csMethod.parameters.length === 0) { csMethod.isVirtual = false; csMethod.isOverride = true; } break; - case 'Equals': + case this._context.toMethodName('equals'): if (csMethod.parameters.length === 1) { csMethod.isVirtual = false; csMethod.isOverride = true; @@ -1262,12 +1288,16 @@ export default class CSharpAstTransformer { break; } - parent.members.push(csMethod); + if (!csMethod.skipEmit) { + parent.members.push(csMethod); + } this._context.registerSymbol(csMethod); + + return csMethod; } - private visitStatement(parent: cs.Node, s: ts.Statement): cs.Statement | null { + protected visitStatement(parent: cs.Node, s: ts.Statement): cs.Statement | null { if (this.shouldSkip(s, true)) { return null; } @@ -1321,14 +1351,14 @@ export default class CSharpAstTransformer { return {} as cs.ThrowStatement; } - private visitEmptyStatement(parent: cs.Node, s: ts.EmptyStatement) { + protected visitEmptyStatement(parent: cs.Node, s: ts.EmptyStatement) { return { nodeType: cs.SyntaxKind.EmptyStatement, parent: parent, tsNode: s } as cs.EmptyStatement; } - private visitDebuggerStatement(parent: cs.Node, s: ts.DebuggerStatement) { + protected visitDebuggerStatement(parent: cs.Node, s: ts.DebuggerStatement) { return {} as cs.ThrowStatement; // { @@ -1339,7 +1369,7 @@ export default class CSharpAstTransformer { // } as cs.ExpressionStatement; } - private visitBlock(parent: cs.Node, block: ts.Block): cs.Block { + protected visitBlock(parent: cs.Node, block: ts.Block): cs.Block { const csBlock: cs.Block = { nodeType: cs.SyntaxKind.Block, parent: parent, @@ -1357,7 +1387,7 @@ export default class CSharpAstTransformer { return csBlock; } - private visitVariableStatement(parent: cs.Node, s: ts.VariableStatement) { + protected visitVariableStatement(parent: cs.Node, s: ts.VariableStatement) { const variableStatement = { nodeType: cs.SyntaxKind.VariableStatement, parent: parent, @@ -1370,7 +1400,7 @@ export default class CSharpAstTransformer { return variableStatement; } - private visitVariableDeclarationList(parent: cs.Node, s: ts.VariableDeclarationList): cs.VariableDeclarationList { + protected visitVariableDeclarationList(parent: cs.Node, s: ts.VariableDeclarationList): cs.VariableDeclarationList { const variableStatement = { nodeType: cs.SyntaxKind.VariableDeclarationList, parent: parent, @@ -1384,7 +1414,7 @@ export default class CSharpAstTransformer { return variableStatement; } - private visitVariableDeclaration(parent: cs.Node, s: ts.VariableDeclaration): cs.VariableDeclaration { + protected visitVariableDeclaration(parent: cs.Node, s: ts.VariableDeclaration): cs.VariableDeclaration { const variableStatement = { nodeType: cs.SyntaxKind.VariableDeclaration, parent: parent, @@ -1398,12 +1428,12 @@ export default class CSharpAstTransformer { const type = this._context.typeChecker.getTypeOfSymbolAtLocation(symbol!, s); variableStatement.name = s.name.text; - if (parent.nodeType === cs.SyntaxKind.CatchClause) { + if (cs.isCatchClause(parent)) { variableStatement.type = { nodeType: cs.SyntaxKind.TypeReference, parent: variableStatement, tsNode: s, - reference: 'AlphaTab.Core.EcmaScript.Error' + reference: this._context.makeExceptionType() } as cs.TypeReference; } else { variableStatement.type = this.createUnresolvedTypeNode(variableStatement, s.type ?? s, type); @@ -1431,7 +1461,7 @@ export default class CSharpAstTransformer { return variableStatement; } - private visitExpressionStatement(parent: cs.Node, s: ts.ExpressionStatement) { + protected visitExpressionStatement(parent: cs.Node, s: ts.ExpressionStatement) { const expressionStatement = { nodeType: cs.SyntaxKind.ExpressionStatement, parent: parent, @@ -1447,7 +1477,7 @@ export default class CSharpAstTransformer { return expressionStatement; } - private visitIfStatement(parent: cs.Node, s: ts.IfStatement) { + protected visitIfStatement(parent: cs.Node, s: ts.IfStatement) { const ifStatement = { nodeType: cs.SyntaxKind.IfStatement, parent: parent, @@ -1462,7 +1492,7 @@ export default class CSharpAstTransformer { } ifStatement.thenStatement = this.visitStatement(ifStatement, s.thenStatement)!; if (!ifStatement.thenStatement) { - return null + return null; } if (s.elseStatement) { @@ -1475,7 +1505,7 @@ export default class CSharpAstTransformer { return ifStatement; } - private visitDoStatement(parent: cs.Node, s: ts.DoStatement) { + protected visitDoStatement(parent: cs.Node, s: ts.DoStatement) { const doStatement = { nodeType: cs.SyntaxKind.DoStatement, parent: parent, @@ -1497,7 +1527,7 @@ export default class CSharpAstTransformer { return doStatement; } - private visitWhileStatement(parent: cs.Node, s: ts.WhileStatement) { + protected visitWhileStatement(parent: cs.Node, s: ts.WhileStatement) { const whileStatement = { nodeType: cs.SyntaxKind.WhileStatement, parent: parent, @@ -1519,7 +1549,7 @@ export default class CSharpAstTransformer { return whileStatement; } - private visitForStatement(parent: cs.Node, s: ts.ForStatement) { + protected visitForStatement(parent: cs.Node, s: ts.ForStatement) { const forStatement = { nodeType: cs.SyntaxKind.ForStatement, parent: parent, @@ -1559,7 +1589,7 @@ export default class CSharpAstTransformer { return forStatement; } - private visitForOfStatement(parent: cs.Node, s: ts.ForOfStatement) { + protected visitForOfStatement(parent: cs.Node, s: ts.ForOfStatement) { const forEachStatement = { nodeType: cs.SyntaxKind.ForEachStatement, parent: parent, @@ -1589,7 +1619,7 @@ export default class CSharpAstTransformer { return forEachStatement; } - private visitForInStatement(parent: cs.Node, s: ts.ForInStatement) { + protected visitForInStatement(parent: cs.Node, s: ts.ForInStatement) { // TODO: Detect raw object iteration and map it const forEachStatement = { nodeType: cs.SyntaxKind.ForEachStatement, @@ -1621,7 +1651,7 @@ export default class CSharpAstTransformer { return forEachStatement; } - private visitBreakStatement(parent: cs.Node, s: ts.BreakStatement) { + protected visitBreakStatement(parent: cs.Node, s: ts.BreakStatement) { const breakStatement = { nodeType: cs.SyntaxKind.BreakStatement, parent: parent, @@ -1631,7 +1661,7 @@ export default class CSharpAstTransformer { return breakStatement; } - private visitContinueStatement(parent: cs.Node, s: ts.ContinueStatement) { + protected visitContinueStatement(parent: cs.Node, s: ts.ContinueStatement) { const continueStatement = { nodeType: cs.SyntaxKind.ContinueStatement, parent: parent, @@ -1641,7 +1671,7 @@ export default class CSharpAstTransformer { return continueStatement; } - private visitReturnStatement(parent: cs.Node, s: ts.ReturnStatement) { + protected visitReturnStatement(parent: cs.Node, s: ts.ReturnStatement) { const returnStatement = { nodeType: cs.SyntaxKind.ReturnStatement, parent: parent, @@ -1658,7 +1688,7 @@ export default class CSharpAstTransformer { return returnStatement; } - private visitSwitchStatement(parent: cs.Node, s: ts.SwitchStatement) { + protected visitSwitchStatement(parent: cs.Node, s: ts.SwitchStatement) { const switchStatement = { nodeType: cs.SyntaxKind.SwitchStatement, parent: parent, @@ -1686,7 +1716,7 @@ export default class CSharpAstTransformer { return switchStatement; } - private visitDefaultClause(parent: cs.SwitchStatement, s: ts.DefaultClause): cs.DefaultClause { + protected visitDefaultClause(parent: cs.SwitchStatement, s: ts.DefaultClause): cs.DefaultClause { const defaultClause = { nodeType: cs.SyntaxKind.DefaultClause, parent: parent, @@ -1704,7 +1734,7 @@ export default class CSharpAstTransformer { return defaultClause; } - private visitCaseClause(parent: cs.SwitchStatement, s: ts.CaseClause) { + protected visitCaseClause(parent: cs.SwitchStatement, s: ts.CaseClause) { if (this.shouldSkip(s, true)) { return null; } @@ -1731,7 +1761,7 @@ export default class CSharpAstTransformer { return caseClause; } - private visitThrowStatement(parent: cs.Node, s: ts.ThrowStatement) { + protected visitThrowStatement(parent: cs.Node, s: ts.ThrowStatement) { const throwStatement = { nodeType: cs.SyntaxKind.ThrowStatement, parent: parent, @@ -1747,7 +1777,7 @@ export default class CSharpAstTransformer { return throwStatement; } - private visitTryStatement(parent: cs.Node, s: ts.TryStatement) { + protected visitTryStatement(parent: cs.Node, s: ts.TryStatement) { const tryStatement = { nodeType: cs.SyntaxKind.TryStatement, parent: parent, @@ -1766,7 +1796,7 @@ export default class CSharpAstTransformer { return tryStatement; } - private visitCatchClause(parent: cs.TryStatement, s: ts.CatchClause): cs.CatchClause { + protected visitCatchClause(parent: cs.TryStatement, s: ts.CatchClause): cs.CatchClause { const catchClause = { nodeType: cs.SyntaxKind.CatchClause, parent: parent, @@ -1781,7 +1811,7 @@ export default class CSharpAstTransformer { return catchClause; } - private visitMethodSignature( + protected visitMethodSignature( parent: cs.ClassDeclaration | cs.InterfaceDeclaration, classElement: ts.MethodSignature ) { @@ -1795,7 +1825,8 @@ export default class CSharpAstTransformer { isOverride: false, isStatic: false, isVirtual: false, - name: this._context.toPascalCase((classElement.name as ts.Identifier).text), + partial: !!ts.getJSDocTags(classElement).find(t => t.tagName.text === 'partial'), + name: this._context.toMethodName((classElement.name as ts.Identifier).text), parameters: [], returnType: this.createUnresolvedTypeNode(null, classElement.type ?? classElement, returnType), visibility: cs.Visibility.None, @@ -1828,13 +1859,19 @@ export default class CSharpAstTransformer { classElement.parameters.forEach(p => this.visitMethodParameter(csMethod, p)); - parent.members.push(csMethod); + if (!csMethod.skipEmit) { + parent.members.push(csMethod); + } this._context.registerSymbol(csMethod); } - private mapVisibility(modifiers: ts.ModifiersArray | undefined): cs.Visibility { - if (modifiers) { - for (const m of modifiers) { + protected mapVisibility(node: ts.Node): cs.Visibility { + if (this._context.isInternal(node)) { + return cs.Visibility.Internal; + } + + if (node.modifiers) { + for (const m of node.modifiers) { switch (m.kind) { case ts.SyntaxKind.PublicKeyword: return cs.Visibility.Public; @@ -1847,11 +1884,11 @@ export default class CSharpAstTransformer { } return cs.Visibility.Public; } - private visitMethodParameter(parent: cs.MethodDeclarationBase, p: ts.ParameterDeclaration): void { + protected visitMethodParameter(parent: cs.MethodDeclarationBase, p: ts.ParameterDeclaration): void { parent.parameters.push(this.makeParameter(parent, p)); } - private makeParameter(csMethod: cs.Node, p: ts.ParameterDeclaration): cs.ParameterDeclaration { + protected makeParameter(csMethod: cs.Node, p: ts.ParameterDeclaration): cs.ParameterDeclaration { const symbol = this._context.typeChecker.getSymbolAtLocation(p.name); const type = this._context.typeChecker.getTypeOfSymbolAtLocation(symbol!, p); @@ -1871,7 +1908,7 @@ export default class CSharpAstTransformer { if (p.initializer) { csParameter.initializer = this.visitExpression(csParameter, p.initializer) ?? undefined; - if (csParameter.initializer && csParameter.initializer.nodeType === cs.SyntaxKind.NullLiteral) { + if (csParameter.initializer && cs.isNullLiteral(csParameter.initializer)) { csParameter.type!.isNullable = true; } } else if (csParameter.type!.isOptional) { @@ -1886,14 +1923,14 @@ export default class CSharpAstTransformer { return csParameter; } - private visitConstructorDeclaration(parent: cs.ClassDeclaration, classElement: ts.ConstructorDeclaration) { + protected visitConstructorDeclaration(parent: cs.ClassDeclaration, classElement: ts.ConstructorDeclaration) { const csConstructor: cs.ConstructorDeclaration = { parent: parent, nodeType: cs.SyntaxKind.ConstructorDeclaration, name: '.ctor', parameters: [], isStatic: false, - visibility: this.mapVisibility(classElement.modifiers), + visibility: this.mapVisibility(classElement), tsNode: classElement, skipEmit: this.shouldSkip(classElement, false) }; @@ -1905,22 +1942,24 @@ export default class CSharpAstTransformer { const block = csConstructor.body as cs.Block; if ( block.statements.length > 0 && - block.statements[0].nodeType === cs.SyntaxKind.ExpressionStatement && - (block.statements[0] as cs.ExpressionStatement).expression.nodeType === - cs.SyntaxKind.InvocationExpression && - ((block.statements[0] as cs.ExpressionStatement).expression as cs.InvocationExpression).expression - .nodeType === cs.SyntaxKind.BaseLiteralExpression + cs.isExpressionStatement(block.statements[0]) && + cs.isInvocationExpression((block.statements[0] as cs.ExpressionStatement).expression) && + cs.isBaseLiteralExpression( + ((block.statements[0] as cs.ExpressionStatement).expression as cs.InvocationExpression).expression + ) ) { - csConstructor.baseConstructorArguments = ((block.statements[0] as cs.ExpressionStatement) - .expression as cs.InvocationExpression).arguments; + csConstructor.baseConstructorArguments = ( + (block.statements[0] as cs.ExpressionStatement).expression as cs.InvocationExpression + ).arguments; block.statements.shift(); } } parent.members.push(csConstructor); + return csConstructor; } - private visitExpression(parent: cs.Node, expression: ts.Expression): cs.Expression | null { + protected visitExpression(parent: cs.Node, expression: ts.Expression): cs.Expression | null { switch (expression.kind) { case ts.SyntaxKind.PrefixUnaryExpression: return this.visitPrefixUnaryExpression(parent, expression as ts.PrefixUnaryExpression); @@ -2011,11 +2050,11 @@ export default class CSharpAstTransformer { tsNode: expression } as cs.Expression; } - private visitSpreadElement(parent: cs.Node, expression: ts.SpreadElement) { + protected visitSpreadElement(parent: cs.Node, expression: ts.SpreadElement) { return this.visitExpression(parent, expression.expression); } - private visitPrefixUnaryExpression(parent: cs.Node, expression: ts.PrefixUnaryExpression) { + protected visitPrefixUnaryExpression(parent: cs.Node, expression: ts.PrefixUnaryExpression) { const csExpr = { parent: parent, tsNode: expression, @@ -2029,14 +2068,35 @@ export default class CSharpAstTransformer { return null; } - if (csExpr.operator === "~") { + if (csExpr.operator === '~') { csExpr.operand = this.makeInt(csExpr.operand); } + // ensure number literals assigned to any/unknown + // are casted explicitly to double (to avoid ending up with ints later expected as doubles) + if (this._context.isUnknownSmartCast(expression)) { + return this.wrapIntoCastToTargetType(csExpr); + } + return csExpr; } - private visitPostfixUnaryExpression(parent: cs.Node, expression: ts.PostfixUnaryExpression) { + public wrapIntoCastToTargetType(expression: cs.Expression): cs.Expression { + const actualType = this._context.typeChecker.getTypeAtLocation(expression.tsNode!); + const cast = { + parent: expression.parent, + nodeType: cs.SyntaxKind.CastExpression, + tsNode: expression.tsNode, + expression: expression, + type: this.createUnresolvedTypeNode(null, expression.tsNode!, actualType) + } as cs.CastExpression; + + cast.expression.parent = cast; + cast.type.parent = cast; + return cast; + } + + protected visitPostfixUnaryExpression(parent: cs.Node, expression: ts.PostfixUnaryExpression) { const csExpr = { parent: parent, tsNode: expression, @@ -2053,7 +2113,7 @@ export default class CSharpAstTransformer { return csExpr; } - private visitNullLiteral(parent: cs.Node, expression: ts.NullLiteral) { + protected visitNullLiteral(parent: cs.Node, expression: ts.NullLiteral) { const csExpr = { parent: parent, tsNode: expression, @@ -2063,7 +2123,7 @@ export default class CSharpAstTransformer { return csExpr; } - private visitBooleanLiteral(parent: cs.Node, expression: ts.BooleanLiteral) { + protected visitBooleanLiteral(parent: cs.Node, expression: ts.BooleanLiteral) { const csExpr = { parent: parent, tsNode: expression, @@ -2074,10 +2134,8 @@ export default class CSharpAstTransformer { return csExpr; } - private visitThisExpression(parent: cs.Node, expression: ts.ThisExpression) { - if (parent.nodeType === cs.SyntaxKind.MemberAccessExpression && - parent.tsSymbol && - this._context.isStaticSymbol(parent.tsSymbol)) { + protected visitThisExpression(parent: cs.Node, expression: ts.ThisExpression) { + if (cs.isMemberAccessExpression(parent) && parent.tsSymbol && this._context.isStaticSymbol(parent.tsSymbol)) { const identifier = { parent: parent, tsNode: expression, @@ -2098,7 +2156,7 @@ export default class CSharpAstTransformer { } } - private visitSuperLiteralExpression(parent: cs.Node, expression: ts.SuperExpression) { + protected visitSuperLiteralExpression(parent: cs.Node, expression: ts.SuperExpression) { const csExpr = { parent: parent, tsNode: expression, @@ -2108,7 +2166,7 @@ export default class CSharpAstTransformer { return csExpr; } - private visitTypeOfExpression(parent: cs.Node, expression: ts.TypeOfExpression) { + protected visitTypeOfExpression(parent: cs.Node, expression: ts.TypeOfExpression) { // AlphaTab.Core.TypeHelper.TypeOf(expr) const csExpr = { parent: parent, @@ -2118,7 +2176,11 @@ export default class CSharpAstTransformer { expression: {} as cs.Expression } as cs.InvocationExpression; - csExpr.expression = this.makeMemberAccess(csExpr, 'AlphaTab.Core.TypeHelper', 'TypeOf'); + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('typeOf') + ); const e = this.visitExpression(csExpr, expression.expression); if (e) { csExpr.arguments.push(e); @@ -2127,7 +2189,7 @@ export default class CSharpAstTransformer { return csExpr; } - private makeMemberAccess(parent: cs.Node, identifier: string, member: string): cs.Node { + protected makeMemberAccess(parent: cs.Node, identifier: string, member: string): cs.Node { const memberAccess = { expression: { nodeType: cs.SyntaxKind.Identifier, @@ -2144,7 +2206,7 @@ export default class CSharpAstTransformer { return memberAccess; } - private visitAwaitExpression(parent: cs.Node, expression: ts.AwaitExpression) { + protected visitAwaitExpression(parent: cs.Node, expression: ts.AwaitExpression) { const awaitExpression = { parent: parent, nodeType: cs.SyntaxKind.AwaitExpression, @@ -2160,7 +2222,7 @@ export default class CSharpAstTransformer { return awaitExpression; } - private visitBinaryExpression(parent: cs.Node, expression: ts.BinaryExpression) { + protected visitBinaryExpression(parent: cs.Node, expression: ts.BinaryExpression) { if (expression.operatorToken.kind === ts.SyntaxKind.InKeyword) { // AlphaTab.Core.TypeHelper.In('Text', expr) const csExpr = { @@ -2171,7 +2233,11 @@ export default class CSharpAstTransformer { expression: {} as cs.Expression } as cs.InvocationExpression; - csExpr.expression = this.makeMemberAccess(csExpr, 'AlphaTab.Core.TypeHelper', 'In'); + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('in') + ); let e = this.visitExpression(csExpr, expression.left)!; if (e) { @@ -2256,8 +2322,8 @@ export default class CSharpAstTransformer { const leftType = this._context.typeChecker.getTypeAtLocation(expression.left); const rightType = this._context.typeChecker.getTypeAtLocation(expression.right); - const isLeftEnum = (leftType.flags & ts.TypeFlags.Enum) || (leftType.flags & ts.TypeFlags.EnumLiteral); - const isRightEnum = (rightType.flags & ts.TypeFlags.Enum) || (rightType.flags & ts.TypeFlags.EnumLiteral); + const isLeftEnum = leftType.flags & ts.TypeFlags.Enum || leftType.flags & ts.TypeFlags.EnumLiteral; + const isRightEnum = rightType.flags & ts.TypeFlags.Enum || rightType.flags & ts.TypeFlags.EnumLiteral; if (!isLeftEnum || !isRightEnum) { const toInt = ((bitOp.left as cs.ParenthesizedExpression).expression = { @@ -2305,6 +2371,7 @@ export default class CSharpAstTransformer { } } + assignment.right = this.makeDouble(assignment.right); return assignment; } else { const binaryExpression = { @@ -2329,22 +2396,56 @@ export default class CSharpAstTransformer { const leftType = this._context.typeChecker.getTypeAtLocation(expression.left); const rightType = this._context.typeChecker.getTypeAtLocation(expression.right); - const isLeftEnum = (leftType.flags & ts.TypeFlags.Enum) || (leftType.flags & ts.TypeFlags.EnumLiteral); - const isRightEnum = (rightType.flags & ts.TypeFlags.Enum) || (rightType.flags & ts.TypeFlags.EnumLiteral); + const isLeftEnum = leftType.flags & ts.TypeFlags.Enum || leftType.flags & ts.TypeFlags.EnumLiteral; + const isRightEnum = rightType.flags & ts.TypeFlags.Enum || rightType.flags & ts.TypeFlags.EnumLiteral; if (!isLeftEnum || !isRightEnum) { switch (expression.operatorToken.kind) { + case ts.SyntaxKind.PlusToken: + case ts.SyntaxKind.PlusEqualsToken: + // string and number concatenation + if ( + leftType.flags & ts.TypeFlags.Number && + rightType.flags & (ts.TypeFlags.String | ts.TypeFlags.StringLiteral) + ) { + binaryExpression.left = this.toInvariantString(binaryExpression.left); + } else if ( + rightType.flags & ts.TypeFlags.Number && + leftType.flags & (ts.TypeFlags.String | ts.TypeFlags.StringLiteral) + ) { + binaryExpression.right = this.toInvariantString(binaryExpression.right); + } + break; case ts.SyntaxKind.AmpersandToken: case ts.SyntaxKind.GreaterThanGreaterThanToken: case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: case ts.SyntaxKind.LessThanLessThanToken: case ts.SyntaxKind.BarToken: case ts.SyntaxKind.CaretToken: - binaryExpression.left = this.makeInt(binaryExpression.left); - binaryExpression.right = this.makeInt(binaryExpression.right); + if (!this.hasBinaryOperationMakeInt(binaryExpression.left)) { + binaryExpression.left = this.makeInt(binaryExpression.left); + } + if (!this.hasBinaryOperationMakeInt(binaryExpression.right)) { + binaryExpression.right = this.makeInt(binaryExpression.right); + } + + let nextParent = parent; + while (cs.isParenthesizedExpression(nextParent)) { + nextParent = nextParent.parent!; + } + + if ( + nextParent.nodeType !== cs.SyntaxKind.BinaryExpression || + (nextParent as cs.BinaryExpression).operator === '=' + ) { + return this.makeDouble(binaryExpression); + } break; case ts.SyntaxKind.SlashToken: - if (expression.left.kind === ts.SyntaxKind.NumericLiteral && expression.right.kind === ts.SyntaxKind.NumericLiteral) { + if (expression.left.kind === ts.SyntaxKind.NumericLiteral) { + binaryExpression.left = this.makeDouble(binaryExpression.left); + } + if (expression.right.kind === ts.SyntaxKind.NumericLiteral) { binaryExpression.right = this.makeDouble(binaryExpression.right); } break; @@ -2355,7 +2456,28 @@ export default class CSharpAstTransformer { } } - private makeDouble(expression: cs.Expression): cs.Expression { + private hasBinaryOperationMakeInt(left: cs.Expression): boolean { + if (cs.isParenthesizedExpression(left)) { + return this.hasBinaryOperationMakeInt(left.expression); + } + + if (left.nodeType !== cs.SyntaxKind.BinaryExpression) { + return false; + } + + switch ((left as cs.BinaryExpression).operator) { + case '&': + case '>>': + case '<<': + case '^': + case '|': + return true; + } + + return false; + } + + protected makeDouble(expression: cs.Expression): cs.Expression { // (double)(expr) const cast = { @@ -2382,7 +2504,7 @@ export default class CSharpAstTransformer { return cast; } - private makeInt(expression: cs.Expression): cs.Expression { + protected makeInt(expression: cs.Expression): cs.Expression { switch (expression.nodeType) { case cs.SyntaxKind.NumericLiteral: if ((expression as cs.NumericLiteral).value.indexOf('.') === -1) { @@ -2416,7 +2538,7 @@ export default class CSharpAstTransformer { return cast; } - private visitConditionalExpression(parent: cs.Node, expression: ts.ConditionalExpression) { + protected visitConditionalExpression(parent: cs.Node, expression: ts.ConditionalExpression) { const conditionalExpression = { parent: parent, nodeType: cs.SyntaxKind.ConditionalExpression, @@ -2444,7 +2566,7 @@ export default class CSharpAstTransformer { return conditionalExpression; } - private makeTruthy(expression: cs.Node, force: boolean = false): cs.Expression { + protected makeTruthy(expression: cs.Node, force: boolean = false): cs.Expression { if (!force) { if (!this._context.isBooleanSmartCast(expression.tsNode!)) { return expression; @@ -2465,19 +2587,19 @@ export default class CSharpAstTransformer { arguments: [] } as cs.InvocationExpression; - const access = call.expression = { + const access = (call.expression = { parent: call, tsNode: expression.tsNode, nodeType: cs.SyntaxKind.MemberAccessExpression, expression: {} as cs.Expression, - member: 'IsTruthy' - } as cs.MemberAccessExpression; + member: this._context.toMethodName('isTruthy') + } as cs.MemberAccessExpression); access.expression = { parent: access, tsNode: expression.tsNode, nodeType: cs.SyntaxKind.Identifier, - text: 'AlphaTab.Core.TypeHelper' + text: this._context.makeTypeName('alphaTab.core.TypeHelper') } as cs.Identifier; expression.parent = call; @@ -2486,8 +2608,8 @@ export default class CSharpAstTransformer { return call; } - private visitFunctionExpression(parent: cs.Node, expression: ts.FunctionExpression) { - if (parent.nodeType === cs.SyntaxKind.ExpressionStatement) { + protected visitFunctionExpression(parent: cs.Node, expression: ts.FunctionExpression) { + if (cs.isExpressionStatement(parent)) { this._context.addTsNodeDiagnostics( expression, 'Local function declarations are not yet supported', @@ -2512,9 +2634,31 @@ export default class CSharpAstTransformer { parent: parent, tsNode: expression, body: {} as cs.Expression, - parameters: [] + parameters: [], + returnType: {} as cs.TypeNode } as cs.LambdaExpression; + const signature = this._context.typeChecker.getSignatureFromDeclaration(expression); + if (!signature) { + this._context.addCsNodeDiagnostics( + lambdaExpression, + 'Could not get signature for function', + ts.DiagnosticCategory.Error + ); + lambdaExpression.returnType = { + nodeType: cs.SyntaxKind.PrimitiveTypeNode, + parent: lambdaExpression, + type: cs.PrimitiveType.Void + } as cs.PrimitiveTypeNode; + } else { + const returnType = signature.getReturnType(); + lambdaExpression.returnType = this.createUnresolvedTypeNode( + lambdaExpression, + expression.type ?? expression, + returnType + ); + } + expression.parameters.forEach(p => { lambdaExpression.parameters.push(this.makeParameter(lambdaExpression, p)); }); @@ -2525,19 +2669,37 @@ export default class CSharpAstTransformer { } } - private visitArrowExpression(parent: cs.Node, expression: ts.ArrowFunction) { + protected visitArrowExpression(parent: cs.Node, expression: ts.ArrowFunction) { const lambdaExpression = { nodeType: cs.SyntaxKind.LambdaExpression, parent: parent, tsNode: expression, body: {} as cs.Expression, - parameters: [] + parameters: [], + returnType: {} as cs.TypeNode } as cs.LambdaExpression; expression.parameters.forEach(p => { lambdaExpression.parameters.push(this.makeParameter(lambdaExpression, p)); }); + const signature = this._context.typeChecker.getSignatureFromDeclaration(expression); + if (!signature) { + this._context.addTsNodeDiagnostics( + expression, + 'Could not find signature from arrow function', + ts.DiagnosticCategory.Error + ); + lambdaExpression.returnType = { + parent: lambdaExpression, + nodeType: cs.SyntaxKind.PrimitiveTypeNode, + type: cs.PrimitiveType.Void + } as cs.PrimitiveTypeNode; + } else { + const returnType = this._context.typeChecker.getReturnTypeOfSignature(signature!); + lambdaExpression.returnType = this.createUnresolvedTypeNode(lambdaExpression, expression, returnType); + } + if (ts.isBlock(expression.body)) { lambdaExpression.body = this.visitBlock(lambdaExpression, expression.body); } else { @@ -2554,7 +2716,7 @@ export default class CSharpAstTransformer { return lambdaExpression; } - private visitRegularExpressionLiteral(parent: cs.Node, expression: ts.RegularExpressionLiteral) { + protected visitRegularExpressionLiteral(parent: cs.Node, expression: ts.RegularExpressionLiteral) { // AlphaTab.Core.TypeHelper.CreateRegex(expr) const csExpr = { parent: parent, @@ -2565,7 +2727,11 @@ export default class CSharpAstTransformer { } as cs.InvocationExpression; const parts = expression.text.split('/'); - csExpr.expression = this.makeMemberAccess(csExpr, 'AlphaTab.Core.TypeHelper', 'CreateRegex'); + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('createRegex') + ); csExpr.arguments.push({ parent: csExpr, nodeType: cs.SyntaxKind.StringLiteral, @@ -2583,16 +2749,24 @@ export default class CSharpAstTransformer { return csExpr; } - private visitNumericLiteral(parent: cs.Node, expression: ts.NumericLiteral) { - return { + protected visitNumericLiteral(parent: cs.Node, expression: ts.NumericLiteral) { + const numeric = { parent: parent, nodeType: cs.SyntaxKind.NumericLiteral, tsNode: expression, value: expression.text } as cs.NumericLiteral; + + // ensure number literals assigned to any/unknown + // are casted explicitly to double (to avoid ending up with ints later expected as doubles) + if (this._context.isUnknownSmartCast(expression)) { + return this.wrapIntoCastToTargetType(numeric); + } + + return numeric; } - private visitNoSubstitutionTemplateLiteral( + protected visitNoSubstitutionTemplateLiteral( parent: cs.Node, expression: ts.NoSubstitutionTemplateLiteral ): cs.Expression { @@ -2606,7 +2780,7 @@ export default class CSharpAstTransformer { return stringLiteral; } - private visitTemplateExpression(parent: cs.Node, expression: ts.TemplateExpression) { + protected visitTemplateExpression(parent: cs.Node, expression: ts.TemplateExpression): cs.Expression { const templateString = { parent: parent, nodeType: cs.SyntaxKind.StringTemplateExpression, @@ -2639,7 +2813,7 @@ export default class CSharpAstTransformer { return templateString; } - private visitTypeAssertionExpression(parent: cs.Node, expression: ts.TypeAssertion) { + protected visitTypeAssertionExpression(parent: cs.Node, expression: ts.TypeAssertion) { const csExpr = { parent: parent, tsNode: expression, @@ -2657,7 +2831,7 @@ export default class CSharpAstTransformer { return csExpr; } - private visitParenthesizedExpression(parent: cs.Node, expression: ts.ParenthesizedExpression) { + protected visitParenthesizedExpression(parent: cs.Node, expression: ts.ParenthesizedExpression) { const csExpr = { parent: parent, tsNode: expression, @@ -2673,8 +2847,10 @@ export default class CSharpAstTransformer { return csExpr; } - private visitArrayLiteralExpression(parent: cs.Node, expression: ts.ArrayLiteralExpression) { - if (this.isMapInitializer(expression)) { + protected visitArrayLiteralExpression(parent: cs.Node, expression: ts.ArrayLiteralExpression) { + if (this.isMapEntry(expression)) { + return this.createMapEntry(parent, expression); + } else if (this.isMapInitializer(expression)) { const csExpr = { parent: parent, tsNode: expression, @@ -2683,7 +2859,11 @@ export default class CSharpAstTransformer { expression: {} as cs.Expression } as cs.InvocationExpression; - csExpr.expression = this.makeMemberAccess(csExpr, 'AlphaTab.Core.TypeHelper', 'CreateMapEntry'); + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('mapInitializer') + ); expression.elements.forEach(e => { const ex = this.visitExpression(csExpr, e); @@ -2692,6 +2872,15 @@ export default class CSharpAstTransformer { } }); + // steal generic from inner element + if ( + csExpr.arguments.length > 0 && + cs.isInvocationExpression(csExpr.arguments[0]) && + cs.isTypeReference(csExpr.arguments[0].expression) + ) { + csExpr.typeArguments = [csExpr.arguments[0].expression]; + } + return csExpr; } else if (this.isSetInitializer(expression)) { const csExpr = { @@ -2702,7 +2891,16 @@ export default class CSharpAstTransformer { expression: {} as cs.Expression } as cs.InvocationExpression; - csExpr.expression = this.makeMemberAccess(csExpr, 'AlphaTab.Core.TypeHelper', 'SetInitializer'); + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('setInitializer') + ); + + const setCreation = expression.parent as ts.NewExpression; + if (setCreation.typeArguments) { + csExpr.typeArguments = setCreation.typeArguments.map(t => this.createUnresolvedTypeNode(csExpr, t)); + } expression.elements.forEach(e => { const ex = this.visitExpression(csExpr, e); @@ -2735,7 +2933,41 @@ export default class CSharpAstTransformer { return csExpr; } } - private isMapInitializer(expression: ts.ArrayLiteralExpression) { + protected createMapEntry(parent: cs.Node, expression: ts.ArrayLiteralExpression): cs.Expression { + const csExpr = { + parent: parent, + tsNode: expression, + nodeType: cs.SyntaxKind.InvocationExpression, + arguments: [], + expression: {} as cs.Expression + } as cs.InvocationExpression; + + csExpr.expression = this.makeMemberAccess( + csExpr, + this._context.makeTypeName('alphaTab.core.TypeHelper'), + this._context.toMethodName('createMapEntry') + ); + + expression.elements.forEach(e => { + const ex = this.visitExpression(csExpr, e); + if (ex) { + csExpr.arguments.push(ex); + } + }); + + return csExpr; + } + + protected isMapInitializer(expression: ts.ArrayLiteralExpression) { + const isCandidate = expression.parent.kind === ts.SyntaxKind.NewExpression; + if (!isCandidate) { + return false; + } + + return this._context.typeChecker.getTypeAtLocation(expression.parent).symbol.name === 'Map'; + } + + protected isMapEntry(expression: ts.ArrayLiteralExpression) { const isCandidate = expression.elements.length === 2 && expression.parent.kind === ts.SyntaxKind.ArrayLiteralExpression && @@ -2752,7 +2984,7 @@ export default class CSharpAstTransformer { return false; } - private isSetInitializer(expression: ts.ArrayLiteralExpression) { + protected isSetInitializer(expression: ts.ArrayLiteralExpression) { const isCandidate = expression.parent.kind === ts.SyntaxKind.NewExpression; if (!isCandidate) { return false; @@ -2761,16 +2993,24 @@ export default class CSharpAstTransformer { return this._context.typeChecker.getTypeAtLocation(expression.parent).symbol.name === 'Set'; } - private visitPropertyAccessExpression(parent: cs.Node, expression: ts.PropertyAccessExpression) { + protected visitPropertyAccessExpression(parent: cs.Node, expression: ts.PropertyAccessExpression) { const memberAccess = { expression: {} as cs.Expression, - member: this._context.toPascalCase(expression.name.text), + member: this._context.toPropertyName(expression.name.text), parent: parent, tsNode: expression, tsSymbol: this._context.typeChecker.getSymbolAtLocation(expression), nodeType: cs.SyntaxKind.MemberAccessExpression } as cs.MemberAccessExpression; + if (memberAccess.tsSymbol) { + if (this._context.isMethodSymbol(memberAccess.tsSymbol)) { + memberAccess.member = this._context.toMethodName(expression.name.text); + } else if (this._context.isPropertySymbol(memberAccess.tsSymbol)) { + memberAccess.member = this._context.toPropertyName(expression.name.text); + } + } + if ( memberAccess.tsSymbol && expression.parent.kind === ts.SyntaxKind.CaseClause && @@ -2782,30 +3022,9 @@ export default class CSharpAstTransformer { if (memberAccess.tsSymbol) { const parentSymbol = (memberAccess.tsSymbol as any).parent as ts.Symbol; if (parentSymbol) { - switch (parentSymbol.name) { - case 'Array': - switch (memberAccess.tsSymbol!.name) { - case 'length': - memberAccess.member = 'Count'; - break; - case 'reverse': - memberAccess.member = 'Reversed'; - break; - case 'push': - memberAccess.member = 'Add'; - break; - } - break; - case 'String': - switch (memberAccess.tsSymbol!.name) { - case 'trimRight': - memberAccess.member = 'TrimEnd'; - break; - case 'trimLeft': - memberAccess.member = 'TrimStart'; - break; - } - break; + const renamed = this.getSymbolName(parentSymbol!, memberAccess.tsSymbol!, memberAccess); + if (renamed) { + memberAccess.member = renamed; } } } @@ -2822,7 +3041,39 @@ export default class CSharpAstTransformer { return this.wrapToSmartCast(parent, memberAccess, expression); } - private visitObjectLiteralExpression(parent: cs.Node, expression: ts.ObjectLiteralExpression) { + protected getSymbolName(parentSymbol: ts.Symbol, symbol: ts.Symbol, expression: cs.Expression): string | null { + switch (parentSymbol.name) { + case 'Array': + switch (symbol.name) { + case 'length': + return 'Count'; + case 'reverse': + return 'Reversed'; + case 'push': + return 'Add'; + } + break; + case 'String': + switch (symbol.name) { + case 'trimRight': + return 'TrimEnd'; + case 'trimLeft': + return 'TrimStart'; + case 'substring': + return 'SubstringIndex'; + } + break; + case 'Number': + switch (symbol.name) { + case 'toString': + return 'ToInvariantString'; + } + break; + } + return null; + } + + protected visitObjectLiteralExpression(parent: cs.Node, expression: ts.ObjectLiteralExpression) { const objectLiteral = { parent: parent, tsNode: expression, @@ -2843,7 +3094,6 @@ export default class CSharpAstTransformer { if (assignment.value) { objectLiteral.properties.push(assignment); } - } else if (ts.isShorthandPropertyAssignment(p)) { const assignment = { parent: objectLiteral, @@ -2856,7 +3106,6 @@ export default class CSharpAstTransformer { if (assignment.value) { objectLiteral.properties.push(assignment); } - } else if (ts.isSpreadAssignment(p)) { this._context.addTsNodeDiagnostics(p, 'Spread operator not supported', ts.DiagnosticCategory.Error); } else if (ts.isMethodDeclaration(p)) { @@ -2872,9 +3121,27 @@ export default class CSharpAstTransformer { parent: objectLiteral, parameters: [], body: {} as cs.Block, - tsNode: p + tsNode: p, + returnType: {} as cs.TypeNode } as cs.LambdaExpression; + const signature = this._context.typeChecker.getSignatureFromDeclaration(p); + if (!signature) { + this._context.addCsNodeDiagnostics( + lambda, + 'Could not get signature for function', + ts.DiagnosticCategory.Error + ); + lambda.returnType = { + nodeType: cs.SyntaxKind.PrimitiveTypeNode, + parent: lambda, + type: cs.PrimitiveType.Void + } as cs.PrimitiveTypeNode; + } else { + const returnType = signature.getReturnType(); + lambda.returnType = this.createUnresolvedTypeNode(lambda, p.type ?? p, returnType); + } + p.parameters.forEach(param => lambda.parameters.push(this.makeParameter(lambda, param))); lambda.body = this.visitBlock(parent, p.body!); @@ -2899,10 +3166,38 @@ export default class CSharpAstTransformer { return objectLiteral; } - private visitElementAccessExpression(parent: cs.Node, expression: ts.ElementAccessExpression) { + protected toInvariantString(expr: cs.Expression): cs.Expression { + const callExpr = { + parent: expr.parent, + arguments: [], + expression: {} as cs.Expression, + nodeType: cs.SyntaxKind.InvocationExpression, + tsNode: expr.tsNode + } as cs.InvocationExpression; + const memberAccess = (callExpr.expression = { + expression: null!, + member: this._context.toPascalCase('toInvariantString'), + parent: callExpr, + tsNode: expr.tsNode, + nodeType: cs.SyntaxKind.MemberAccessExpression + } as cs.MemberAccessExpression); + + const par = { + parent: memberAccess, + nodeType: cs.SyntaxKind.ParenthesizedExpression, + tsNode: expr.tsNode, + tsSymbol: expr.tsSymbol, + expression: expr + } as cs.ParenthesizedExpression; + expr.parent = par; + memberAccess.expression = par; + + return callExpr; + } + + protected visitElementAccessExpression(parent: cs.Node, expression: ts.ElementAccessExpression) { // Enum[value] => value.ToString() - const enumType = this._context.typeChecker.getTypeAtLocation(expression.expression); - if (enumType?.symbol && enumType.symbol.flags & ts.SymbolFlags.RegularEnum) { + if (this.isEnumToString(expression)) { const callExpr = { parent: parent, arguments: [], @@ -2913,7 +3208,7 @@ export default class CSharpAstTransformer { const memberAccess = (callExpr.expression = { expression: {} as cs.Expression, - member: 'ToString', + member: this._context.toPascalCase('toString'), parent: callExpr, tsNode: expression, nodeType: cs.SyntaxKind.MemberAccessExpression @@ -2932,7 +3227,8 @@ export default class CSharpAstTransformer { argumentExpression: {} as cs.Expression, parent: parent, tsNode: expression, - nodeType: cs.SyntaxKind.ElementAccessExpression + nodeType: cs.SyntaxKind.ElementAccessExpression, + nullSafe: !!expression.questionDotToken } as cs.ElementAccessExpression; elementAccess.expression = this.visitExpression(elementAccess, expression.expression)!; @@ -2950,7 +3246,8 @@ export default class CSharpAstTransformer { if (type) { type = this._context.typeChecker.getNonNullableType(type); } - const isArrayAccessor = !symbol || (type && type.symbol && !!type.symbol.members?.has(ts.escapeLeadingUnderscores('slice'))); + const isArrayAccessor = + !symbol || (type && type.symbol && !!type.symbol.members?.has(ts.escapeLeadingUnderscores('slice'))); if (isArrayAccessor) { const csArg = { expression: {} as cs.Expression, @@ -2979,7 +3276,12 @@ export default class CSharpAstTransformer { return this.wrapToSmartCast(parent, elementAccess, expression); } - private visitCallExpression(parent: cs.Node, expression: ts.CallExpression) { + protected isEnumToString(expression: ts.ElementAccessExpression): boolean { + const enumType = this._context.typeChecker.getTypeAtLocation(expression.expression); + return !!(enumType?.symbol && enumType.symbol.flags & ts.SymbolFlags.RegularEnum); + } + + protected visitCallExpression(parent: cs.Node, expression: ts.CallExpression) { if (this.isBind(expression)) { return this.visitExpression(parent, (expression.expression as ts.PropertyAccessExpression).expression); } @@ -2992,12 +3294,22 @@ export default class CSharpAstTransformer { nodeType: cs.SyntaxKind.InvocationExpression } as cs.InvocationExpression; + // number.ToString + const isNumberToString = + ts.isPropertyAccessExpression(expression.expression) && + this._context.typeChecker.getTypeAtLocation(expression.expression.expression).flags & ts.TypeFlags.Number && + (expression.expression.name as ts.Identifier).text === 'toString' && + expression.arguments.length === 0; + callExpression.expression = this.visitExpression(callExpression, expression.expression)!; if (!callExpression.expression) { return null; } - if (ts.isPropertyAccessExpression(expression.expression) && expression.expression.name.text === 'setPrototypeOf') { + if ( + ts.isPropertyAccessExpression(expression.expression) && + expression.expression.name.text === 'setPrototypeOf' + ) { return null; } @@ -3008,31 +3320,6 @@ export default class CSharpAstTransformer { } }); - // number.ToString - const isNumberToString = ts.isPropertyAccessExpression(expression.expression) - && this._context.typeChecker.getTypeAtLocation(expression.expression.expression).flags & ts.TypeFlags.Number - && (expression.expression.name as ts.Identifier).text === 'toString' - && expression.arguments.length === 0; - - if (isNumberToString) { - const invariantCultureInfo = { - parent: parent, - nodeType: cs.SyntaxKind.MemberAccessExpression, - tsNode: expression, - expression: null!, - member: 'InvariantCulture' - } as cs.MemberAccessExpression; - - invariantCultureInfo.expression = { - parent: invariantCultureInfo, - tsNode: expression.expression, - nodeType: cs.SyntaxKind.Identifier, - text: 'System.Globalization.CultureInfo' - } as cs.Identifier; - - callExpression.arguments.push(invariantCultureInfo); - } - if (expression.typeArguments) { callExpression.typeArguments = []; expression.typeArguments.forEach(a => @@ -3042,14 +3329,14 @@ export default class CSharpAstTransformer { return this.makeTruthy(callExpression); } - private isBind(expression: ts.CallExpression) { + protected isBind(expression: ts.CallExpression) { if (ts.isPropertyAccessExpression(expression.expression)) { return expression.expression.name.text === 'bind' && expression.arguments.length === 1; } return false; } - private visitNewExpression(parent: cs.Node, expression: ts.NewExpression) { + protected visitNewExpression(parent: cs.Node, expression: ts.NewExpression) { const symbol = this._context.typeChecker.getSymbolAtLocation(expression.expression); let type: ts.Type | undefined = undefined; if (symbol) { @@ -3066,14 +3353,6 @@ export default class CSharpAstTransformer { } as cs.NewExpression; newExpression.type.parent = newExpression; - if (expression.arguments) { - expression.arguments.forEach(a => { - const e = this.visitExpression(newExpression, a); - if (e) { - newExpression.arguments.push(e) - } - }); - } if (expression.typeArguments) { csType.typeArguments = []; @@ -3103,7 +3382,16 @@ export default class CSharpAstTransformer { } } - if (type && type.symbol && type.symbol.name == 'ArrayConstructor' && newExpression.arguments.length === 1) { + if (expression.arguments) { + expression.arguments.forEach(a => { + const e = this.visitExpression(newExpression, a); + if (e) { + newExpression.arguments.push(e); + } + }); + } + + if (type && type.symbol && type.symbol.name === 'ArrayConstructor' && newExpression.arguments.length === 1) { const toInt = { parent: newExpression, nodeType: cs.SyntaxKind.CastExpression, @@ -3132,13 +3420,13 @@ export default class CSharpAstTransformer { return newExpression; } - private getDeclarationOrAssignmentType(): ts.Type | undefined { + protected getDeclarationOrAssignmentType(): ts.Type | undefined { return this._declarationOrAssignmentTypeStack.length === 0 ? undefined : this._declarationOrAssignmentTypeStack[this._declarationOrAssignmentTypeStack.length - 1]; } - private visitAsExpression(parent: cs.Node, expression: ts.AsExpression) { + protected visitAsExpression(parent: cs.Node, expression: ts.AsExpression): cs.Expression | null { const castExpression = { type: this.createUnresolvedTypeNode(null, expression.type), expression: {} as cs.Expression, @@ -3156,7 +3444,7 @@ export default class CSharpAstTransformer { return castExpression; } - private visitNonNullExpression(parent: cs.Node, expression: ts.NonNullExpression) { + protected visitNonNullExpression(parent: cs.Node, expression: ts.NonNullExpression) { if (this._context.isValueTypeExpression(expression)) { const valueAccessExpression = { expression: {} as cs.Expression, @@ -3189,7 +3477,7 @@ export default class CSharpAstTransformer { } } - private visitIdentifier(parent: cs.Node, expression: ts.Identifier) { + protected visitIdentifier(parent: cs.Node, expression: ts.Identifier) { if (expression.text === 'undefined') { return { parent: parent, @@ -3203,9 +3491,11 @@ export default class CSharpAstTransformer { tsNode: expression, tsSymbol: this._context.typeChecker.getSymbolAtLocation(expression), nodeType: cs.SyntaxKind.Identifier, - text: expression.text + text: '' } as cs.Identifier; + identifier.text = this.getIdentifierName(identifier, expression); + if (identifier.tsSymbol) { switch (expression.parent.kind) { case ts.SyntaxKind.PropertyAccessExpression: @@ -3224,20 +3514,23 @@ export default class CSharpAstTransformer { } break; } - } return this.wrapToSmartCast(parent, identifier, expression); } - private wrapToSmartCast(parent: cs.Node, node: cs.Node, expression: ts.Expression): cs.Expression { + protected getIdentifierName(identifier: cs.Identifier, expression: ts.Identifier): string { + return expression.text; + } + + protected wrapToSmartCast(parent: cs.Node, node: cs.Node, expression: ts.Expression): cs.Expression { if (node.tsSymbol) { if ( (node.tsSymbol.flags & ts.SymbolFlags.Property) === ts.SymbolFlags.Property || (node.tsSymbol.flags & ts.SymbolFlags.Variable) === ts.SymbolFlags.Variable || (node.tsSymbol.flags & ts.SymbolFlags.EnumMember) === ts.SymbolFlags.EnumMember || (node.tsSymbol.flags & ts.SymbolFlags.FunctionScopedVariable) === - ts.SymbolFlags.FunctionScopedVariable || + ts.SymbolFlags.FunctionScopedVariable || (node.tsSymbol.flags & ts.SymbolFlags.BlockScopedVariable) === ts.SymbolFlags.BlockScopedVariable ) { let smartCastType = this._context.getSmartCastType(expression); @@ -3291,13 +3584,22 @@ export default class CSharpAstTransformer { } as cs.NonNullExpression; } } + + if (this._context.isNonNullSmartCast(expression)) { + return { + parent: parent, + nodeType: cs.SyntaxKind.NonNullExpression, + tsNode: expression, + expression: node + } as cs.NonNullExpression; + } } } return this.makeTruthy(node); } - private visitStringLiteral(parent: cs.Node, expression: ts.Identifier) { + protected visitStringLiteral(parent: cs.Node, expression: ts.Identifier) { const stringLiteral = { parent: parent, tsNode: expression, @@ -3308,11 +3610,11 @@ export default class CSharpAstTransformer { return stringLiteral; } - private removeExtension(fileName: string) { + protected removeExtension(fileName: string) { return fileName.substring(0, fileName.lastIndexOf('.')); } - private mapOperator(operator: ts.SyntaxKind): string { + protected mapOperator(operator: ts.SyntaxKind): string { switch (operator) { case ts.SyntaxKind.PlusPlusToken: return '++'; diff --git a/src.compiler/csharp/CSharpEmitterContext.ts b/src.compiler/csharp/CSharpEmitterContext.ts index 92c6055c7..c53661ce3 100644 --- a/src.compiler/csharp/CSharpEmitterContext.ts +++ b/src.compiler/csharp/CSharpEmitterContext.ts @@ -1,7 +1,6 @@ import * as cs from './CSharpAst'; import * as ts from 'typescript'; import * as path from 'path'; -import { indexOf } from 'lodash'; type SymbolKey = string; @@ -9,14 +8,17 @@ export default class CSharpEmitterContext { private _fileLookup: Map = new Map(); private _symbolLookup: Map = new Map(); private _exportedSymbols: Map = new Map(); + private _virtualSymbols: Map = new Map(); private _symbolConst: Map = new Map(); private _diagnostics: ts.Diagnostic[] = []; private _unresolvedTypeNodes: cs.UnresolvedTypeNode[] = []; private _program: ts.Program; public typeChecker: ts.TypeChecker; + public noPascalCase: boolean = false; public csharpFiles: cs.SourceFile[] = []; + public processingSkippedElement: boolean = false; public get compilerOptions(): ts.CompilerOptions { return this._program.getCompilerOptions(); } @@ -29,6 +31,33 @@ export default class CSharpEmitterContext { return this.typeChecker.getTypeAtLocation(n); } + public toMethodName(text: string): string { + return this.toPascalCase(this.toIdentifier(text)); + } + + public toPropertyName(text: string): string { + return this.toPascalCase(this.toIdentifier(text)); + } + + public toIdentifier(text: string): string { + return text.replace(/[^a-zA-Z0-9_]/g, m => { + return ( + { + '#': 'Hash', + '@': 'At' + }[m] ?? '_' + ); + }); + } + + public isMethodSymbol(tsSymbol: ts.Symbol) { + return (tsSymbol.flags & ts.SymbolFlags.Method) !== 0; + } + + public isPropertySymbol(tsSymbol: ts.Symbol) { + return (tsSymbol.flags & ts.SymbolFlags.Property) !== 0; + } + public isTypeAssignable(targetType: ts.Type, actualType: ts.Type) { if (targetType.flags === ts.TypeFlags.Any || targetType.flags === ts.TypeFlags.Unknown) { return true; @@ -40,6 +69,9 @@ export default class CSharpEmitterContext { } public registerUnresolvedTypeNode(unresolved: cs.UnresolvedTypeNode) { + if (this.processingSkippedElement) { + return; + } this._unresolvedTypeNodes.push(unresolved); } @@ -52,8 +84,7 @@ export default class CSharpEmitterContext { case cs.SyntaxKind.ClassDeclaration: case cs.SyntaxKind.InterfaceDeclaration: case cs.SyntaxKind.EnumDeclaration: - case cs.SyntaxKind.DelegateDeclaration: - return this.getFullName(csSymbol as cs.NamedTypeDeclaration); + return this.getFullName(csSymbol as cs.NamedTypeDeclaration, expr); } return csSymbol.name; } else if ( @@ -62,17 +93,17 @@ export default class CSharpEmitterContext { expr.tsSymbol.flags & ts.SymbolFlags.ConstEnum || expr.tsSymbol.flags & ts.SymbolFlags.RegularEnum ) { - return this.buildCoreNamespace(expr.tsSymbol) + expr.tsSymbol.name; + return this.buildCoreNamespace(expr.tsSymbol) + this.toCoreTypeName(expr.tsSymbol.name); } else if (expr.tsSymbol.flags & ts.SymbolFlags.Function) { if (this.isTestFunction(expr.tsSymbol)) { - return 'AlphaTab.Test.Globals.' + this.toPascalCase(expr.tsSymbol.name); + return this.toPascalCase('alphaTab.test') + '.Globals.' + this.toPascalCase(expr.tsSymbol.name); } - return 'AlphaTab.Core.Globals.' + this.toPascalCase(expr.tsSymbol.name); + return this.toPascalCase('alphaTab.core') + '.Globals.' + this.toPascalCase(expr.tsSymbol.name); } else if ( (expr.tsSymbol.flags & ts.SymbolFlags.FunctionScopedVariable && this.isGlobalVariable(expr.tsSymbol)) || (expr.tsSymbol.flags & ts.SymbolFlags.NamespaceModule && this.isKnownModule(expr.tsSymbol)) ) { - return 'AlphaTab.Core.Globals.' + this.toPascalCase(expr.tsSymbol.name); + return this.toPascalCase('alphaTab.core') + '.Globals.' + this.toPascalCase(expr.tsSymbol.name); } } return undefined; @@ -104,7 +135,7 @@ export default class CSharpEmitterContext { return false; } - public getFullName(type: cs.NamedTypeDeclaration): string { + public getFullName(type: cs.NamedTypeDeclaration, expr?: cs.Node): string { if (!type.parent) { return ''; } @@ -112,14 +143,17 @@ export default class CSharpEmitterContext { case cs.SyntaxKind.ClassDeclaration: case cs.SyntaxKind.InterfaceDeclaration: case cs.SyntaxKind.EnumDeclaration: - case cs.SyntaxKind.DelegateDeclaration: - return this.getFullName(type.parent as cs.NamedTypeDeclaration) + '.' + type.name; + return this.getFullName(type.parent as cs.NamedTypeDeclaration) + '.' + this.getClassName(type, expr); case cs.SyntaxKind.NamespaceDeclaration: - return (type.parent as cs.NamespaceDeclaration).namespace + '.' + type.name; + return (type.parent as cs.NamespaceDeclaration).namespace + '.' + this.getClassName(type, expr); } return ''; } + protected getClassName(type: cs.NamedTypeDeclaration, expr?: cs.Node) { + return type.name; + } + public resolveAllUnresolvedTypeNodes() { for (let node of this._unresolvedTypeNodes) { let resolved = this.resolveType(node); @@ -308,38 +342,7 @@ export default class CSharpEmitterContext { mapValueType = this.getTypeFromTsType(node, mapType.typeArguments[1]); } - let isValueType = false; - if (mapValueType) { - switch (mapValueType.nodeType) { - case cs.SyntaxKind.PrimitiveTypeNode: - switch ((mapValueType as cs.PrimitiveTypeNode).type) { - case cs.PrimitiveType.Bool: - case cs.PrimitiveType.Int: - case cs.PrimitiveType.Double: - isValueType = true; - break; - } - break; - case cs.SyntaxKind.TypeReference: - const ref = (mapValueType as cs.TypeReference).reference; - if (typeof ref !== 'string') { - switch (ref.nodeType) { - case cs.SyntaxKind.EnumDeclaration: - isValueType = true; - break; - } - } - break; - } - } - - return { - nodeType: cs.SyntaxKind.TypeReference, - parent: node.parent, - tsNode: node.tsNode, - reference: this.buildCoreNamespace(tsSymbol) + (isValueType ? 'ValueTypeMap' : 'Map'), - typeArguments: [mapKeyType, mapValueType] - } as cs.TypeReference; + return this.createMapType(tsSymbol, node, mapKeyType!, mapValueType!); case 'Array': const arrayType = tsType as ts.TypeReference; let arrayElementType: cs.TypeNode | null = null; @@ -358,13 +361,7 @@ export default class CSharpEmitterContext { } as cs.PrimitiveTypeNode; } - return { - nodeType: cs.SyntaxKind.ArrayTypeNode, - parent: node.parent, - tsNode: node.tsNode, - elementType: arrayElementType - } as cs.ArrayTypeNode; - + return this.createArrayListType(tsSymbol, node, arrayElementType); case ts.InternalSymbolName.Type: let csType: cs.TypeNode | null = null; @@ -383,6 +380,57 @@ export default class CSharpEmitterContext { } } + protected createArrayListType(tsSymbol: ts.Symbol, node: cs.Node, arrayElementType: cs.TypeNode): cs.TypeNode { + return { + nodeType: cs.SyntaxKind.ArrayTypeNode, + parent: node.parent, + tsNode: node.tsNode, + elementType: arrayElementType + } as cs.ArrayTypeNode; + } + + protected createMapType( + symbol: ts.Symbol, + node: cs.Node, + mapKeyType: cs.TypeNode, + mapValueType: cs.TypeNode + ): cs.TypeNode { + return { + nodeType: cs.SyntaxKind.MapTypeNode, + parent: node.parent, + tsNode: node.tsNode, + keyType: mapKeyType, + valueType: mapValueType, + valueIsValueType: this.isCsValueType(mapValueType), + keyIsValueType: this.isCsValueType(mapKeyType) + } as cs.MapTypeNode; + } + + protected isCsValueType(mapValueType: cs.TypeNode) { + if (mapValueType) { + switch (mapValueType.nodeType) { + case cs.SyntaxKind.PrimitiveTypeNode: + switch ((mapValueType as cs.PrimitiveTypeNode).type) { + case cs.PrimitiveType.Bool: + case cs.PrimitiveType.Int: + case cs.PrimitiveType.Double: + return true; + } + break; + case cs.SyntaxKind.TypeReference: + const ref = (mapValueType as cs.TypeReference).reference; + if (typeof ref !== 'string') { + switch (ref.nodeType) { + case cs.SyntaxKind.EnumDeclaration: + return true; + } + } + break; + } + } + return false; + } + private resolveFunctionTypeFromTsType(node: cs.Node, tsType: ts.Type): cs.TypeNode | null { // typescript compiler API somehow does not provide proper type symbols // for function types, we need to attempt resolving the types via the function type declaration @@ -470,30 +518,28 @@ export default class CSharpEmitterContext { } } - if ( - returnType.nodeType === cs.SyntaxKind.PrimitiveTypeNode && - (returnType as cs.PrimitiveTypeNode).type === cs.PrimitiveType.Void - ) { - return { - nodeType: cs.SyntaxKind.TypeReference, - parent: node.parent, - tsNode: node.tsNode, - reference: 'System.Action', - typeArguments: parameterTypes - } as cs.TypeReference; - } else { - parameterTypes.push(returnType); - return { - nodeType: cs.SyntaxKind.TypeReference, - parent: node.parent, - tsNode: node.tsNode, - reference: 'System.Func', - typeArguments: parameterTypes - } as cs.TypeReference; - } + return this.createBasicFunctionType(node, returnType, parameterTypes); + } + + protected createBasicFunctionType( + node: cs.Node, + returnType: cs.TypeNode, + parameterTypes: cs.TypeNode[] + ): cs.TypeNode { + return { + nodeType: cs.SyntaxKind.FunctionTypeNode, + parent: node.parent, + tsNode: node.tsNode, + parameterTypes: parameterTypes, + returnType: returnType + } as cs.FunctionTypeNode; } - private resolveUnionType(parent: cs.Node, tsType: ts.Type, typeArguments?: cs.UnresolvedTypeNode[]): cs.TypeNode | null { + private resolveUnionType( + parent: cs.Node, + tsType: ts.Type, + typeArguments?: cs.UnresolvedTypeNode[] + ): cs.TypeNode | null { if (!tsType.isUnion()) { return null; } @@ -571,9 +617,9 @@ export default class CSharpEmitterContext { isOptional: isOptional } as cs.TypeReference; } - + private isNodeEmitted(node: cs.Node): boolean { - if ('skipEmit' in node && node.skipEmit as boolean) { + if ('skipEmit' in node && (node.skipEmit as boolean)) { return false; } else if (node.parent) { return this.isNodeEmitted(node.parent); @@ -734,26 +780,53 @@ export default class CSharpEmitterContext { return null; } - private buildCoreNamespace(aliasSymbol: ts.Symbol) { + public makeExceptionType(): cs.TypeReferenceType { + return this.makeTypeName('system.Exception'); + } + + public makeTypeName(tsName: string): string { + const parts = tsName.split('.'); + let result = ''; + for (let i = 0; i < parts.length; i++) { + if (i > 0) { + result += '.'; + } + if (i === parts.length - 1) { + result += parts[i]; + } else { + result += this.toPascalCase(parts[i]); + } + } + return result; + } + + protected buildCoreNamespace(aliasSymbol: ts.Symbol) { let suffix = ''; - for (const decl of aliasSymbol.declarations) { - let fileName = path.basename(decl.getSourceFile().fileName).toLowerCase(); - if (fileName.startsWith('lib.') && fileName.endsWith('.d.ts')) { - fileName = fileName.substring(4, fileName.length - 5); - if (fileName.length) { - suffix = fileName.split('.').map(s => { - if (s.match(/es[0-9]{4}/)) { - return '.EcmaScript'; - } - if (s.match(/es[0-9]{1}/)) { - return '.EcmaScript'; - } - return '.' + this.toPascalCase(s); - })[0]; + + if (aliasSymbol.declarations) { + for (const decl of aliasSymbol.declarations) { + let fileName = path.basename(decl.getSourceFile().fileName).toLowerCase(); + if (fileName.startsWith('lib.') && fileName.endsWith('.d.ts')) { + fileName = fileName.substring(4, fileName.length - 5); + if (fileName.length) { + suffix = fileName.split('.').map(s => { + if (s.match(/es[0-9]{4}/)) { + return '.' + this.toPascalCase('ecmaScript'); + } + if (s.match(/es[0-9]{1}/)) { + return '.' + this.toPascalCase('ecmaScript'); + } + return '.' + this.toPascalCase(s); + })[0]; + } } } } - return `AlphaTab.Core${suffix}.`; + + return this.toPascalCase('alphaTab.core') + suffix + '.'; + } + protected toCoreTypeName(s: string) { + return s; } public toPascalCase(text: string): string { @@ -761,7 +834,18 @@ export default class CSharpEmitterContext { return this.kebabCaseToPascalCase(text); } - return text ? text.substr(0, 1).toUpperCase() + text.substr(1) : ''; + if (this.noPascalCase) { + return text; + } + + if (!text) { + return ''; + } + + return text + .split('.') + .map(p => p.substr(0, 1).toUpperCase() + p.substr(1)) + .join('.'); } private kebabCaseToPascalCase(text: string): string { @@ -808,8 +892,8 @@ export default class CSharpEmitterContext { const declaration = symbol.valueDeclaration ? symbol.valueDeclaration : symbol.declarations && symbol.declarations.length > 0 - ? symbol.declarations[0] - : undefined; + ? symbol.declarations[0] + : undefined; if (declaration) { return symbol.name + '_' + declaration.getSourceFile().fileName + '_' + declaration.pos; @@ -829,6 +913,14 @@ export default class CSharpEmitterContext { return symbol; } + public isUnknownSmartCast(expression: ts.Expression) { + const smartCastType = this.getSmartCastType(expression); + return ( + smartCastType && + ((smartCastType.flags & ts.TypeFlags.Any) !== 0 || (smartCastType.flags & ts.TypeFlags.Unknown) !== 0) + ); + } + public isBooleanSmartCast(tsNode: ts.Node) { let tsParent = tsNode.parent; if (!tsParent) { @@ -901,9 +993,14 @@ export default class CSharpEmitterContext { // unwrap symbol of expression to get declared type let symbol = this.typeChecker.getSymbolAtLocation(expression); - if (!symbol || !symbol.declarations || symbol.declarations.length === 0) { + if (!symbol) { + return undefined; + } + const declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { return undefined; } + if (symbol.flags & ts.SymbolFlags.Alias) { symbol = this.typeChecker.getAliasedSymbol(symbol); } @@ -912,7 +1009,7 @@ export default class CSharpEmitterContext { } // declared type must be nullable - let declaredType = this.typeChecker.getTypeAtLocation(symbol.declarations[0]); + let declaredType = this.typeChecker.getTypeAtLocation(declarations[0]); if (!this.isNullableType(declaredType)) { return undefined; } @@ -939,22 +1036,88 @@ export default class CSharpEmitterContext { ); } + public isNonNullSmartCast(expression: ts.Expression): boolean { + // if the parent is already casting, we have no "smart" cast. + if ( + expression.parent.kind === ts.SyntaxKind.AsExpression || + (ts.isBinaryExpression(expression.parent) && + expression.parent.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) + ) { + return false; + } + + let contextualType = this.typeChecker.getContextualType(expression); + if (!contextualType) { + return false; + } + + // we consider the expression as smart casted if the declared symbol has a different + // contextual type than the declared type. + let symbol = this.typeChecker.getSymbolAtLocation(expression); + if (!symbol) { + return false; + } + const declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { + return false; + } + + if (symbol.flags & ts.SymbolFlags.Alias) { + symbol = this.typeChecker.getAliasedSymbol(symbol); + } + + if ( + symbol.flags & ts.SymbolFlags.Interface || + symbol.flags & ts.SymbolFlags.Class || + symbol.flags & ts.SymbolFlags.BlockScopedVariable || + symbol.flags & ts.SymbolFlags.FunctionScopedVariable + ) { + return false; + } + + let declaredType = this.typeChecker.getTypeAtLocation(declarations[0]); + if (!this.isNullableType(declaredType)) { + return false; + } + + return contextualType == this.typeChecker.getNonNullableType(declaredType); + } + public getSmartCastType(expression: ts.Expression): ts.Type | null { // if the parent is already casting, we have no "smart" cast. if (expression.parent.kind === ts.SyntaxKind.AsExpression) { return null; } + if ( + expression.parent.kind === ts.SyntaxKind.NonNullExpression && + expression.parent.parent.kind === ts.SyntaxKind.AsExpression + ) { + return null; + } + // For Enum[value] we do not smart cast value to a number - if (ts.isElementAccessExpression(expression.parent) && - expression.parent.argumentExpression === expression) { + if (ts.isElementAccessExpression(expression.parent) && expression.parent.argumentExpression === expression) { return null; } // we consider the expression as smart casted if the declared symbol has a different // contextual type than the declared type. let symbol = this.typeChecker.getSymbolAtLocation(expression); - if (!symbol || !symbol.declarations || symbol.declarations.length === 0) { + if (!symbol) { + // smartcast to unknown? + let contextualType = this.typeChecker.getContextualType(expression); + if ( + contextualType && + ((contextualType.flags & ts.TypeFlags.Any) !== 0 || (contextualType.flags & ts.TypeFlags.Unknown) !== 0) + ) { + return contextualType; + } + + return null; + } + const declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { return null; } @@ -974,7 +1137,7 @@ export default class CSharpEmitterContext { } } - let declaredType = this.typeChecker.getTypeAtLocation(symbol.declarations[0]); + let declaredType = this.typeChecker.getTypeAtLocation(declarations[0]); let contextualTypeNullable = contextualType; contextualType = this.typeChecker.getNonNullableType(contextualType); @@ -1020,6 +1183,14 @@ export default class CSharpEmitterContext { } } + // enum literal to same enum type + if ( + contextualType.flags & ts.TypeFlags.EnumLiteral && + (declaredType.symbol as any)?.parent == contextualType.symbol + ) { + return null; + } + return contextualType !== declaredType && !this.isTypeAssignable(contextualType, declaredType) ? contextualTypeNullable : null; @@ -1060,7 +1231,12 @@ export default class CSharpEmitterContext { return false; } - public isOverride(classElement: ts.ClassElement): boolean { + public markAsSubclassed(classElement: ts.Symbol) { + const key = this.getSymbolKey(classElement); + this._virtualSymbols.set(key, true); + } + + public markOverride(classElement: ts.ClassElement): boolean { let parent: ts.Node = classElement; while (parent.kind !== ts.SyntaxKind.ClassDeclaration) { if (parent.parent) { @@ -1081,41 +1257,63 @@ export default class CSharpEmitterContext { return false; } - if (this.hasAnyBaseTypeClassMember(classType, classElement.name!.getText())) { - return true; - } - - return false; - } - private hasAnyBaseTypeClassMember(classType: ts.InterfaceType, memberName: string) { - const baseTypes = classType.getBaseTypes(); - if (!baseTypes) { - return false; - } + const overridden = this.getOverriddenMembers(classType, classElement); + if (overridden.length > 0) { + const member = + this.typeChecker.getSymbolAtLocation(classElement) ?? + this.typeChecker.getSymbolAtLocation(classElement.name!); + this._virtualSymbols.set(this.getSymbolKey(member), true); - for (const baseType of baseTypes) { - if (baseType.isClass() && this.hasClassMember(baseType, memberName)) { - return true; + for (const s of overridden) { + const symbolKey = this.getSymbolKey(s); + this._virtualSymbols.set(symbolKey, true); } } - return false; + return overridden.length > 0; } - private hasClassMember(baseType: ts.InterfaceType, name: string): boolean { - if ( - baseType.symbol && - baseType.symbol.members && - baseType.symbol.members.has(ts.escapeLeadingUnderscores(name)) - ) { - return true; + protected getOverriddenMembers(classType: ts.InterfaceType, classElement: ts.ClassElement): ts.Symbol[] { + const symbols: ts.Symbol[] = []; + this.collectOverriddenMembersByName(symbols, classType, classElement.name!.getText(), false, false); + return symbols; + } + + protected collectOverriddenMembersByName( + symbols: ts.Symbol[], + classType: ts.InterfaceType, + memberName: string, + includeOwnMembers: boolean = false, + allowInterfaces: boolean = false + ) { + const member = classType.symbol?.members?.get(ts.escapeLeadingUnderscores(memberName)); + if (includeOwnMembers && member) { + symbols.push(member); } - return this.hasAnyBaseTypeClassMember(baseType, name); + const baseTypes = classType.getBaseTypes(); + if (baseTypes) { + for (const baseType of baseTypes) { + if ((allowInterfaces && baseType.isClassOrInterface()) || baseType.isClass()) { + this.collectOverriddenMembersByName(symbols, baseType, memberName, true, allowInterfaces); + } + } + } } public isValueTypeExpression(expression: ts.NonNullExpression) { - const tsType = this.typeChecker.getTypeAtLocation(expression); + let tsType: ts.Type; + if (ts.isIdentifier(expression.expression)) { + const symbol = this.typeChecker.getSymbolAtLocation(expression.expression); + if (symbol?.valueDeclaration) { + tsType = this.typeChecker.getTypeAtLocation(symbol.valueDeclaration); + } else { + tsType = this.typeChecker.getTypeAtLocation(expression); + } + } else { + tsType = this.typeChecker.getTypeAtLocation(expression); + } + return this.isValueType(tsType); } @@ -1136,31 +1334,104 @@ export default class CSharpEmitterContext { return false; } + public isInternal(node: ts.Node) { + return !!ts.getJSDocTags(node).find(t => t.tagName.text === 'internal'); + } + public rewriteVisibilities() { - const visited: Set = new Set(); + const visitedVisibility: Set = new Set(); + const visitedVirtual: Map = new Map(); for (const kvp of this._symbolLookup) { const symbolKey = this.getSymbolKey(kvp[1].tsSymbol!); switch (kvp[1].nodeType) { case cs.SyntaxKind.ClassDeclaration: - case cs.SyntaxKind.DelegateDeclaration: case cs.SyntaxKind.EnumDeclaration: case cs.SyntaxKind.InterfaceDeclaration: - if (!visited.has(symbolKey)) { - const csType = kvp[1] as cs.NamedTypeDeclaration; - const shouldBePublic = !!ts.getJSDocTags(csType.tsNode!).find(t => t.tagName.text === 'csharp_public'); + const csType = kvp[1] as cs.NamedTypeDeclaration; + if (!visitedVisibility.has(symbolKey)) { + const shouldBePublic = !!ts + .getJSDocTags(csType.tsNode!) + .find(t => t.tagName.text === 'csharp_public'); if (csType.visibility === cs.Visibility.Public || shouldBePublic) { if (this._exportedSymbols.has(symbolKey) || shouldBePublic) { - this.makePublic(csType, visited); + this.makePublic(csType, visitedVisibility); } else { csType.visibility = cs.Visibility.Internal; } } } + + if (this.makeVirtual(csType, visitedVirtual)) { + csType.hasVirtualMembersOrSubClasses = true; + } + break; } } } + private makeVirtual(node: cs.Node, visited: Map): boolean { + const x = this.getSymbolKey(this.getSymbolForDeclaration(node.tsNode!)); + if (visited.has(x)) { + return visited.get(x)!; + } + + let hasVirtualMember = false; + + switch (node.nodeType) { + case cs.SyntaxKind.ClassDeclaration: + const csClass = node as cs.ClassDeclaration; + csClass.members.forEach(m => { + if (this.makeVirtual(m, visited)) { + hasVirtualMember = true; + } + }); + + let baseClass = csClass.baseClass; + while (baseClass != null) { + if (cs.isTypeReference(baseClass)) { + const ref = baseClass.reference; + if (cs.isNode(ref) && cs.isClassDeclaration(ref)) { + ref.hasVirtualMembersOrSubClasses = true; + baseClass = ref; + } else { + break; + } + } else { + break; + } + } + + break; + + case cs.SyntaxKind.MethodDeclaration: + const csMethod = node as cs.MethodDeclaration; + + const methodKey = this.getSymbolKey(csMethod.tsSymbol!); + if (!csMethod.isOverride && this._virtualSymbols.has(methodKey)) { + csMethod.isVirtual = true; + hasVirtualMember = true; + } + + break; + + case cs.SyntaxKind.PropertyDeclaration: + const csProperty = node as cs.PropertyDeclaration; + + const propKey = this.getSymbolKey(csProperty.tsSymbol!); + if (!csProperty.isOverride && this._virtualSymbols.has(propKey)) { + csProperty.isVirtual = true; + hasVirtualMember = true; + } + + break; + } + + visited.set(x, hasVirtualMember); + + return hasVirtualMember; + } + private makePublic(node: cs.Node, visited: Set) { if (node.tsSymbol) { const x = this.getSymbolKey(node.tsSymbol); @@ -1185,7 +1456,7 @@ export default class CSharpEmitterContext { csClass.members.forEach(m => { if (m.visibility == cs.Visibility.Public || m.visibility == cs.Visibility.Protected) { - this.makePublic(m, visited) + this.makePublic(m, visited); } }); break; @@ -1202,7 +1473,7 @@ export default class CSharpEmitterContext { } csInterface.members.forEach(m => { - this.makePublic(m, visited) + this.makePublic(m, visited); }); break; @@ -1242,12 +1513,20 @@ export default class CSharpEmitterContext { this.makePublic(csArrayType.elementType, visited); } break; + case cs.SyntaxKind.MapTypeNode: + const mapType = node as cs.MapTypeNode; + this.makePublic(mapType.keyType, visited); + this.makePublic(mapType.valueType, visited); + break; } } public isStaticSymbol(tsSymbol: ts.Symbol) { - return !!tsSymbol.declarations.find(d => d.modifiers && - !!d.modifiers.find(m => m.kind === ts.SyntaxKind.StaticKeyword) + return ( + (tsSymbol.flags & ts.SymbolFlags.EnumMember) !== 0 || + !!tsSymbol.declarations?.find( + d => d.modifiers && !!d.modifiers.find(m => m.kind === ts.SyntaxKind.StaticKeyword) + ) ); } @@ -1255,6 +1534,10 @@ export default class CSharpEmitterContext { if (type.isUnion()) { type = this.typeChecker.getNonNullableType(type); } - return ((type.flags & ts.TypeFlags.String) || (type.flags & ts.TypeFlags.StringLiteral)); + return type.flags & ts.TypeFlags.String || type.flags & ts.TypeFlags.StringLiteral; + } + + public getDefaultUsings(): string[] { + return [this.toPascalCase('system'), this.toPascalCase('alphaTab') + '.' + this.toPascalCase('core')]; } } diff --git a/src.compiler/typescript/CloneEmitter.ts b/src.compiler/typescript/CloneEmitter.ts index 343212181..1a0d5fb93 100644 --- a/src.compiler/typescript/CloneEmitter.ts +++ b/src.compiler/typescript/CloneEmitter.ts @@ -4,17 +4,16 @@ */ import * as path from 'path'; import * as ts from 'typescript'; -import createEmitter from './EmitterBase' +import createEmitter from './EmitterBase'; import { addNewLines } from '../BuilderHelpers'; -import { getTypeWithNullableInfo } from '../BuilderHelpers'; -import { unwrapArrayItemType } from '../BuilderHelpers'; +import { getTypeWithNullableInfo, unwrapArrayItemType } from '../BuilderHelpers'; function removeExtension(fileName: string) { return fileName.substring(0, fileName.lastIndexOf('.')); } function toImportPath(fileName: string) { - return "@" + removeExtension(fileName).split('\\').join('/'); + return '@' + removeExtension(fileName).split('\\').join('/'); } function isClonable(type: ts.Type): boolean { @@ -32,7 +31,11 @@ function isClonable(type: ts.Type): boolean { function isCloneMember(propertyDeclaration: ts.PropertyDeclaration) { if (propertyDeclaration.modifiers) { - if (propertyDeclaration.modifiers.find(m => m.kind === ts.SyntaxKind.StaticKeyword || m.kind === ts.SyntaxKind.ReadonlyKeyword)) { + if ( + propertyDeclaration.modifiers.find( + m => m.kind === ts.SyntaxKind.StaticKeyword || m.kind === ts.SyntaxKind.ReadonlyKeyword + ) + ) { return false; } @@ -48,34 +51,37 @@ function isCloneMember(propertyDeclaration: ts.PropertyDeclaration) { return true; } -function generateClonePropertyStatements(prop: ts.PropertyDeclaration, typeChecker: ts.TypeChecker, - importer: (name: string, module: string) => void): ts.Statement[] { - const propertyType = getTypeWithNullableInfo(typeChecker, prop.type!); +function generateClonePropertyStatements( + prop: ts.PropertyDeclaration, + typeChecker: ts.TypeChecker, + importer: (name: string, module: string) => void +): ts.Statement[] { + const propertyType = getTypeWithNullableInfo(typeChecker, prop.type!, true); const statements: ts.Statement[] = []; const propertyName = (prop.name as ts.Identifier).text; function assign(expr: ts.Expression) { - return [ts.factory.createExpressionStatement( - ts.factory.createAssignment( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('clone'), - propertyName - ), - expr + return [ + ts.factory.createExpressionStatement( + ts.factory.createAssignment( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('clone'), propertyName), + expr + ) ) - )]; + ]; } const arrayItemType = unwrapArrayItemType(propertyType.type!, typeChecker); if (arrayItemType) { if (isClonable(arrayItemType)) { - const collectionAddMethod = ts.getJSDocTags(prop) + const collectionAddMethod = ts + .getJSDocTags(prop) .filter(t => t.tagName.text === 'clone_add') - .map(t => t.comment ?? "")[0]; + .map(t => t.comment ?? '')[0] as string; - importer(arrayItemType.symbol!.name + "Cloner", './' + arrayItemType.symbol!.name + "Cloner"); + importer(arrayItemType.symbol!.name + 'Cloner', './' + arrayItemType.symbol!.name + 'Cloner'); const loopItems = [ ...assign(ts.factory.createArrayLiteralExpression(undefined)), @@ -85,61 +91,61 @@ function generateClonePropertyStatements(prop: ts.PropertyDeclaration, typeCheck [ts.factory.createVariableDeclaration('i')], ts.NodeFlags.Const ), - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName + ts.factory.createNonNullExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('original'), propertyName) ), ts.factory.createBlock([ ts.factory.createExpressionStatement( collectionAddMethod - // clone.addProp(ItemTypeCloner.clone(i)) - ? ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('clone'), - collectionAddMethod - ), - undefined, - [ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(arrayItemType.symbol!.name + "Cloner"), - 'clone' - ), - undefined, - [ - ts.factory.createIdentifier('i') - ] - )] - ) - // clone.prop.push(ItemTypeCloner.clone(i)) - : ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('clone'), - propertyName - ), - 'push' - ), - undefined, - [ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(arrayItemType.symbol!.name + "Cloner"), - 'clone' - ), - undefined, - [ - ts.factory.createIdentifier('i') - ] - )] - ) + ? // clone.addProp(ItemTypeCloner.clone(i)) + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('clone'), + collectionAddMethod + ), + undefined, + [ + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(arrayItemType.symbol!.name + 'Cloner'), + 'clone' + ), + undefined, + [ts.factory.createIdentifier('i')] + ) + ] + ) + : // clone.prop.push(ItemTypeCloner.clone(i)) + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('clone'), + propertyName + ), + 'push' + ), + undefined, + [ + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(arrayItemType.symbol!.name + 'Cloner'), + 'clone' + ), + undefined, + [ts.factory.createIdentifier('i')] + ) + ] + ) ) ]) - )]; + ) + ]; if (propertyType.isNullable) { // if(original.prop) { // clone.prop = []; // for(const i of original.prop) { clone.addProp(ItemTypeCloner.clone(i)); } - // // or + // // or // for(const i of original.prop) { clone.prop.add(ItemTypeCloner.clone(i)); } // } statements.push( @@ -148,46 +154,42 @@ function generateClonePropertyStatements(prop: ts.PropertyDeclaration, typeCheck ts.factory.createIdentifier('original'), propertyName ), - ts.factory.createBlock( - loopItems - ), + ts.factory.createBlock(loopItems), undefined ) - ) + ); } else { // clone.prop = []; // for(const i of original.prop) { clone.addProp(ItemTypeCloner.clone(i)); } - // // or + // // or // for(const i of original.prop) { clone.prop.add(ItemTypeCloner.clone(i)); } statements.push(...loopItems); } } else { - const sliceCall = - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName - ), - 'slice' - ), - undefined, - [] - ); + const sliceCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('original'), propertyName), + 'slice' + ), + undefined, + [] + ); if (propertyType.isNullable) { - statements.push(...assign( - ts.factory.createConditionalExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName - ), - ts.factory.createToken(ts.SyntaxKind.QuestionToken), - sliceCall, - ts.factory.createToken(ts.SyntaxKind.ColonToken), - ts.factory.createNull() + statements.push( + ...assign( + ts.factory.createConditionalExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('original'), + propertyName + ), + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + sliceCall, + ts.factory.createToken(ts.SyntaxKind.ColonToken), + ts.factory.createNull() + ) ) - )); + ); } else { // clone.prop = original.prop.splice() statements.push(...assign(sliceCall)); @@ -195,88 +197,97 @@ function generateClonePropertyStatements(prop: ts.PropertyDeclaration, typeCheck } } else { if (isClonable(propertyType.type!)) { - importer(propertyType.type.symbol!.name + "Cloner", './' + propertyType.type.symbol!.name + "Cloner"); + importer(propertyType.type.symbol!.name + 'Cloner', './' + propertyType.type.symbol!.name + 'Cloner'); // clone.prop = original.prop ? TypeNameCloner.clone(original.prop) : null - statements.push(...assign( - ts.factory.createConditionalExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName - ), - ts.factory.createToken(ts.SyntaxKind.QuestionToken), - ts.factory.createCallExpression( + statements.push( + ...assign( + ts.factory.createConditionalExpression( ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(propertyType.type.symbol!.name + "Cloner"), - 'clone' + ts.factory.createIdentifier('original'), + propertyName ), - undefined, - [ + ts.factory.createToken(ts.SyntaxKind.QuestionToken), + ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName - ) - ] - ), - ts.factory.createToken(ts.SyntaxKind.ColonToken), - ts.factory.createNull() + ts.factory.createIdentifier(propertyType.type.symbol!.name + 'Cloner'), + 'clone' + ), + undefined, + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('original'), + propertyName + ) + ] + ), + ts.factory.createToken(ts.SyntaxKind.ColonToken), + ts.factory.createNull() + ) ) - )); + ); } else { // clone.prop = original.prop - statements.push(...assign( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('original'), - propertyName + statements.push( + ...assign( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('original'), propertyName) ) - )); + ); } } return statements; } -function generateCloneBody(program: ts.Program, input: ts.ClassDeclaration, importer: (name: string, module: string) => void): ts.Block { +function generateCloneBody( + program: ts.Program, + input: ts.ClassDeclaration, + importer: (name: string, module: string) => void +): ts.Block { const typeChecker = program.getTypeChecker(); - const propertiesToSerialize = input.members.filter( - m => ts.isPropertyDeclaration(m) && isCloneMember(m) - ).map(m => m as ts.PropertyDeclaration); + const propertiesToSerialize = input.members + .filter(m => ts.isPropertyDeclaration(m) && isCloneMember(m)) + .map(m => m as ts.PropertyDeclaration); const bodyStatements = propertiesToSerialize.reduce((stmts, prop) => { stmts.push(...generateClonePropertyStatements(prop, typeChecker, importer)); return stmts; }, new Array()); - return ts.factory.createBlock(addNewLines([ - // const clone = new Type(); - ts.factory.createVariableStatement( - undefined, - ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration( - 'clone', - undefined, - undefined, - ts.factory.createNewExpression( - ts.factory.createIdentifier(input.name!.text), - undefined, - [] - ) + return ts.factory.createBlock( + addNewLines([ + // const clone = new Type(); + ts.factory.createVariableStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + 'clone', + undefined, + undefined, + ts.factory.createNewExpression(ts.factory.createIdentifier(input.name!.text), undefined, []) + ) + ], + ts.NodeFlags.Const ) - ], ts.NodeFlags.Const) - ), - ...bodyStatements, - // return json; - ts.factory.createReturnStatement(ts.factory.createIdentifier('clone')) - ])); + ), + ...bodyStatements, + // return json; + ts.factory.createReturnStatement(ts.factory.createIdentifier('clone')) + ]) + ); } - -function createCloneMethod(program: ts.Program, input: ts.ClassDeclaration, importer: (name: string, module: string) => void) { +function createCloneMethod( + program: ts.Program, + input: ts.ClassDeclaration, + importer: (name: string, module: string) => void +) { return ts.factory.createMethodDeclaration( undefined, [ ts.factory.createModifier(ts.SyntaxKind.PublicKeyword), - ts.factory.createModifier(ts.SyntaxKind.StaticKeyword), + ts.factory.createModifier(ts.SyntaxKind.StaticKeyword) ], undefined, 'clone', @@ -289,19 +300,13 @@ function createCloneMethod(program: ts.Program, input: ts.ClassDeclaration, impo undefined, 'original', undefined, - ts.factory.createTypeReferenceNode( - input.name!.text, - undefined - ), + ts.factory.createTypeReferenceNode(input.name!.text, undefined), undefined ) ], - ts.factory.createTypeReferenceNode( - input.name!.text, - undefined - ), + ts.factory.createTypeReferenceNode(input.name!.text, undefined), generateCloneBody(program, input, importer) - ) + ); } export default createEmitter('cloneable', (program, input) => { @@ -314,49 +319,52 @@ export default createEmitter('cloneable', (program, input) => { const statements: ts.Statement[] = []; function importer(name: string, module: string) { - statements.push(ts.factory.createImportDeclaration( - undefined, - undefined, - ts.factory.createImportClause( - false, + statements.push( + ts.factory.createImportDeclaration( + undefined, undefined, - ts.factory.createNamedImports([ts.factory.createImportSpecifier( + ts.factory.createImportClause( + false, undefined, - ts.factory.createIdentifier(name) - )]) - ), - ts.factory.createStringLiteral(module) - )) + ts.factory.createNamedImports([ + ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name)) + ]) + ), + ts.factory.createStringLiteral(module) + ) + ); } - statements.push(ts.factory.createClassDeclaration( - [], - [ - ts.factory.createModifier(ts.SyntaxKind.ExportKeyword), - ], - input.name!.text + 'Cloner', - undefined, - undefined, - [ - createCloneMethod(program, input, importer) - ] - )); - - const sourceFile = ts.factory.createSourceFile([ - ts.factory.createImportDeclaration( + statements.push( + ts.factory.createClassDeclaration( + [], + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + input.name!.text + 'Cloner', undefined, undefined, - ts.factory.createImportClause(false, + [createCloneMethod(program, input, importer)] + ) + ); + + const sourceFile = ts.factory.createSourceFile( + [ + ts.factory.createImportDeclaration( undefined, - ts.factory.createNamedImports([ts.factory.createImportSpecifier( + undefined, + ts.factory.createImportClause( + false, undefined, - ts.factory.createIdentifier(input.name!.text) - )]) + ts.factory.createNamedImports([ + ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(input.name!.text)) + ]) + ), + ts.factory.createStringLiteral(toImportPath(sourceFileName)) ), - ts.factory.createStringLiteral(toImportPath(sourceFileName)) - ), - ...statements - ], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None); + ...statements + ], + ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), + ts.NodeFlags.None + ); return sourceFile; -}); \ No newline at end of file +}); diff --git a/src.compiler/typescript/Serializer.common.ts b/src.compiler/typescript/Serializer.common.ts new file mode 100644 index 000000000..f45aed9de --- /dev/null +++ b/src.compiler/typescript/Serializer.common.ts @@ -0,0 +1,70 @@ +import * as ts from 'typescript'; +import * as path from 'path'; + +export interface JsonProperty { + partialNames: boolean; + property: ts.PropertyDeclaration; + jsonNames: string[]; + target?: string; + isReadOnly: boolean; +} + +export interface JsonSerializable { + isStrict: boolean; + hasToJsonExtension: boolean; + hasSetPropertyExtension: boolean; + properties: JsonProperty[]; +} + + +export function isImmutable(type: ts.Type | null): boolean { + if (!type || !type.symbol) { + return false; + } + + const declaration = type.symbol.valueDeclaration; + if (declaration) { + return !!ts.getJSDocTags(declaration).find(t => t.tagName.text === 'json_immutable'); + } + + return false; +} + +export function createStringUnknownMapNode(): ts.TypeNode { + return ts.factory.createTypeReferenceNode('Map', [ + ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) + ]); +} + +function removeExtension(fileName: string) { + return fileName.substring(0, fileName.lastIndexOf('.')); +} + +export function toImportPath(fileName: string) { + return '@' + removeExtension(fileName).split('\\').join('/'); +} + +export function findModule(type: ts.Type, options: ts.CompilerOptions) { + if (type.symbol && type.symbol.declarations) { + for (const decl of type.symbol.declarations) { + const file = decl.getSourceFile(); + if (file) { + const relative = path.relative(path.join(path.resolve(options.baseUrl!)), path.resolve(file.fileName)); + return toImportPath(relative); + } + } + + return './' + type.symbol.name; + } + + return ''; +} + +export function findSerializerModule(type: ts.Type, options: ts.CompilerOptions) { + let module = findModule(type, options); + const importPath = module.split('/'); + importPath.splice(1, 0, 'generated'); + importPath[importPath.length - 1] = type.symbol!.name + 'Serializer'; + return importPath.join('/'); +} diff --git a/src.compiler/typescript/Serializer.fromJson.ts b/src.compiler/typescript/Serializer.fromJson.ts new file mode 100644 index 000000000..f1b5e5299 --- /dev/null +++ b/src.compiler/typescript/Serializer.fromJson.ts @@ -0,0 +1,36 @@ +import * as ts from 'typescript'; +import { addNewLines, createNodeFromSource, setMethodBody } from '../BuilderHelpers'; +import { JsonSerializable } from './Serializer.common'; + +function generateFromJsonBody(serializable: JsonSerializable, importer: (name: string, module: string) => void) { + importer('JsonHelper', '@src/io/JsonHelper'); + return ts.factory.createBlock(addNewLines([ + createNodeFromSource(`if(!m) { + return; + }`, ts.SyntaxKind.IfStatement), + serializable.isStrict + ? createNodeFromSource( + `JsonHelper.forEach(m, (v, k) => this.setProperty(obj, k, v));`, + ts.SyntaxKind.ExpressionStatement + ) + : createNodeFromSource( + `JsonHelper.forEach(m, (v, k) => this.setProperty(obj, k.toLowerCase(), v));`, + ts.SyntaxKind.ExpressionStatement + ) + ])); +} + +export function createFromJsonMethod( + input: ts.ClassDeclaration, + serializable: JsonSerializable, + importer: (name: string, module: string) => void +) { + const methodDecl = createNodeFromSource( + `public class Serializer { + public static fromJson(obj: ${input.name!.text}, m: unknown): void { + } + }`, + ts.SyntaxKind.MethodDeclaration + ); + return setMethodBody(methodDecl, generateFromJsonBody(serializable, importer)); +} diff --git a/src.compiler/typescript/Serializer.setProperty.ts b/src.compiler/typescript/Serializer.setProperty.ts new file mode 100644 index 000000000..d2263914d --- /dev/null +++ b/src.compiler/typescript/Serializer.setProperty.ts @@ -0,0 +1,588 @@ +import * as ts from 'typescript'; +import { addNewLines, createNodeFromSource, setMethodBody } from '../BuilderHelpers'; +import { isPrimitiveType } from '../BuilderHelpers'; +import { hasFlag } from '../BuilderHelpers'; +import { getTypeWithNullableInfo } from '../BuilderHelpers'; +import { isTypedArray } from '../BuilderHelpers'; +import { unwrapArrayItemType } from '../BuilderHelpers'; +import { isMap } from '../BuilderHelpers'; +import { isEnumType } from '../BuilderHelpers'; +import { isNumberType } from '../BuilderHelpers'; +import { wrapToNonNull } from '../BuilderHelpers'; +import { + createStringUnknownMapNode, + findModule, + findSerializerModule, + isImmutable, + JsonProperty, + JsonSerializable +} from './Serializer.common'; + +function isPrimitiveFromJson(type: ts.Type, typeChecker: ts.TypeChecker) { + if (!type) { + return false; + } + + const isArray = isTypedArray(type); + const arrayItemType = unwrapArrayItemType(type, typeChecker); + + if (hasFlag(type, ts.TypeFlags.Unknown)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.Number)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.String)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.Boolean)) { + return true; + } + + if (arrayItemType) { + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Number)) { + return true; + } + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.String)) { + return true; + } + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Boolean)) { + return true; + } + } else if (type.symbol) { + switch (type.symbol.name) { + case 'Uint8Array': + case 'Uint16Array': + case 'Uint32Array': + case 'Int8Array': + case 'Int16Array': + case 'Int32Array': + case 'Float32Array': + case 'Float64Array': + return true; + } + } + + return null; +} + +function cloneTypeNode(node: T): T { + if (ts.isUnionTypeNode(node)) { + return ts.factory.createUnionTypeNode(node.types.map(cloneTypeNode)) as any as T; + } else if ( + node.kind === ts.SyntaxKind.StringKeyword || + node.kind === ts.SyntaxKind.NumberKeyword || + node.kind === ts.SyntaxKind.BooleanKeyword || + node.kind === ts.SyntaxKind.UnknownKeyword || + node.kind === ts.SyntaxKind.AnyKeyword || + node.kind === ts.SyntaxKind.VoidKeyword + ) { + return ts.factory.createKeywordTypeNode(node.kind) as any as T; + } else if (ts.isLiteralTypeNode(node)) { + return ts.factory.createLiteralTypeNode(node.literal) as any as T; + } else if (ts.isArrayTypeNode(node)) { + return ts.factory.createArrayTypeNode(cloneTypeNode(node.elementType)) as any as T; + } else if (ts.isTypeReferenceNode(node)) { + return ts.factory.createTypeReferenceNode(cloneTypeNode(node.typeName)) as any as T; + } else if (ts.isIdentifier(node)) { + return ts.factory.createIdentifier(node.text) as any as T; + } else if (ts.isQualifiedName(node)) { + if (typeof node.right === 'string') { + return ts.factory.createQualifiedName(cloneTypeNode(node.left), node.right) as any as T; + } else { + return ts.factory.createQualifiedName(cloneTypeNode(node.left), cloneTypeNode(node.right)) as any as T; + } + } + + throw new Error(`Unsupported TypeNode: '${ts.SyntaxKind[node.kind]}' extend type node cloning`); +} + +function generateSetPropertyBody( + program: ts.Program, + serializable: JsonSerializable, + importer: (name: string, module: string) => void +) { + const statements: ts.Statement[] = []; + const cases: ts.CaseOrDefaultClause[] = []; + + const typeChecker = program.getTypeChecker(); + for (const prop of serializable.properties) { + const jsonNames = prop.jsonNames.map(j => j.toLowerCase()); + const caseValues: string[] = jsonNames.filter(j => j !== ''); + const fieldName = (prop.property.name as ts.Identifier).text; + + const caseStatements: ts.Statement[] = []; + + const type = getTypeWithNullableInfo(typeChecker, prop.property.type, true); + + const assignField = function (expr: ts.Expression): ts.Statement { + return ts.factory.createExpressionStatement( + ts.factory.createAssignment( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), + expr + ) + ); + }; + + if (type.isUnionType) { + caseStatements.push( + assignField( + ts.factory.createAsExpression( + type.isNullable + ? ts.factory.createIdentifier('v') + : ts.factory.createNonNullExpression(ts.factory.createIdentifier('v')), + cloneTypeNode(prop.property.type!) + ) + ) + ); + caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); + } else if (isPrimitiveFromJson(type.type!, typeChecker)) { + caseStatements.push( + assignField( + ts.factory.createAsExpression( + type.isNullable + ? ts.factory.createIdentifier('v') + : ts.factory.createNonNullExpression(ts.factory.createIdentifier('v')), + cloneTypeNode(prop.property.type!) + ) + ) + ); + caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); + } else if (isEnumType(type.type)) { + importer(type.type.symbol!.name, findModule(type.type, program.getCompilerOptions())); + importer('JsonHelper', '@src/io/JsonHelper'); + if (type.isNullable) { + caseStatements.push( + createNodeFromSource( + `obj.${fieldName} = JsonHelper.parseEnum<${type.type.symbol.name}>(v, ${type.type.symbol.name});`, + ts.SyntaxKind.ExpressionStatement + ) + ); + } else { + caseStatements.push( + createNodeFromSource( + `obj.${fieldName} = JsonHelper.parseEnum<${type.type.symbol.name}>(v, ${type.type.symbol.name})!;`, + ts.SyntaxKind.ExpressionStatement + ) + ); + } + caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); + } else if (isTypedArray(type.type!)) { + const arrayItemType = unwrapArrayItemType(type.type!, typeChecker)!; + const collectionAddMethod = + (ts + .getJSDocTags(prop.property) + .filter(t => t.tagName.text === 'json_add') + .map(t => t.comment ?? '')[0] as string) ?? `${fieldName}.push`; + + // obj.fieldName = []; + // for(const i of value) { + // obj.addFieldName(Type.FromJson(i)); + // } + // or + // for(const __li of value) { + // obj.fieldName.push(Type.FromJson(__li)); + // } + + let itemSerializer = arrayItemType.symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(arrayItemType, program.getCompilerOptions())); + importer(arrayItemType.symbol.name, findModule(arrayItemType, program.getCompilerOptions())); + + const loopItems = [ + createNodeFromSource( + `obj.${fieldName} = [];`, + ts.SyntaxKind.ExpressionStatement + ), + createNodeFromSource( + `for(const o of (v as (Map | null)[])) { + const i = new ${arrayItemType.symbol.name}(); + ${itemSerializer}.fromJson(i, o); + obj.${collectionAddMethod}(i) + }`, + ts.SyntaxKind.ForOfStatement + ) + ]; + + if (type.isNullable) { + caseStatements.push( + ts.factory.createIfStatement(ts.factory.createIdentifier('v'), ts.factory.createBlock(loopItems)) + ); + } else { + caseStatements.push(...loopItems); + } + caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); + } else if (isMap(type.type)) { + const mapType = type.type as ts.TypeReference; + if (!isPrimitiveType(mapType.typeArguments![0])) { + throw new Error('only Map maps are supported extend if needed!'); + } + + let mapKey: ts.Expression; + if (isEnumType(mapType.typeArguments![0])) { + importer( + mapType.typeArguments![0].symbol!.name, + findModule(mapType.typeArguments![0], program.getCompilerOptions()) + ); + importer('JsonHelper', '@src/io/JsonHelper'); + mapKey = createNodeFromSource( + `JsonHelper.parseEnum<${mapType.typeArguments![0].symbol!.name}>(k, ${ + mapType.typeArguments![0].symbol!.name + })!`, + ts.SyntaxKind.NonNullExpression + ); + } else if (isNumberType(mapType.typeArguments![0])) { + mapKey = createNodeFromSource(`parseInt(k)`, ts.SyntaxKind.CallExpression); + } else { + mapKey = ts.factory.createIdentifier('k'); + } + + let mapValue; + let itemSerializer: string = ''; + if (isPrimitiveFromJson(mapType.typeArguments![1], typeChecker)) { + mapValue = ts.factory.createAsExpression( + ts.factory.createIdentifier('v'), + ts.isTypeReferenceNode(prop.property.type!) && prop.property.type.typeArguments + ? cloneTypeNode(prop.property.type.typeArguments[1]) + : ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + ); + } else { + itemSerializer = mapType.typeArguments![1].symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(mapType.typeArguments![1], program.getCompilerOptions())); + importer( + mapType.typeArguments![1]!.symbol.name, + findModule(mapType.typeArguments![1], program.getCompilerOptions()) + ); + mapValue = ts.factory.createIdentifier('i'); + } + + const collectionAddMethod = + (ts + .getJSDocTags(prop.property) + .filter(t => t.tagName.text === 'json_add') + .map(t => t.comment ?? '')[0] as string) || fieldName + '.set'; + + caseStatements.push( + assignField( + ts.factory.createNewExpression( + ts.factory.createIdentifier('Map'), + [ + typeChecker.typeToTypeNode(mapType.typeArguments![0], undefined, undefined)!, + typeChecker.typeToTypeNode(mapType.typeArguments![1], undefined, undefined)! + ], + [] + ) + ) + ); + + caseStatements.push( + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JsonHelper'), 'forEach'), + undefined, + [ + ts.factory.createIdentifier('v'), + ts.factory.createArrowFunction( + undefined, + undefined, + [ + ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'v'), + ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'k') + ], + undefined, + ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), + ts.factory.createBlock( + addNewLines( + [ + itemSerializer.length > 0 && + createNodeFromSource( + `const i = new ${mapType.typeArguments![1].symbol.name}();`, + ts.SyntaxKind.VariableStatement + ), + itemSerializer.length > 0 && + createNodeFromSource( + `${itemSerializer}.fromJson(i, v as Map)`, + ts.SyntaxKind.ExpressionStatement + ), + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + collectionAddMethod + ? ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + collectionAddMethod + ) + : ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + ts.factory.createIdentifier(fieldName) + ), + ts.factory.createIdentifier('set') + ), + undefined, + [mapKey, mapValue] + ) + ) + ].filter(s => !!s) as ts.Statement[] + ) + ) + ) + ] + ) + ) + ); + + caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); + } else if (isImmutable(type.type)) { + let itemSerializer = type.type.symbol.name; + importer(itemSerializer, findModule(type.type, program.getCompilerOptions())); + + // obj.fieldName = TypeName.fromJson(value)! + // return true; + caseStatements.push( + createNodeFromSource( + `obj.${fieldName} = ${itemSerializer}.fromJson(v)!;`, + ts.SyntaxKind.ExpressionStatement + ) + ); + caseStatements.push( + createNodeFromSource(`return true;`, ts.SyntaxKind.ReturnStatement) + ); + } else { + // for complex types it is a bit more tricky + // if the property matches exactly, we use fromJson + // if the property starts with the field name, we try to set a sub-property + const jsonNameArray = ts.factory.createArrayLiteralExpression( + jsonNames.map(n => ts.factory.createStringLiteral(n)) + ); + + let itemSerializer = type.type.symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(type.type, program.getCompilerOptions())); + if (type.isNullable) { + importer(type.type.symbol!.name, findModule(type.type, program.getCompilerOptions())); + } + + // TODO if no partial name support, simply generate cases + statements.push( + ts.factory.createIfStatement( + // if(["", "core"].indexOf(property) >= 0) + ts.factory.createBinaryExpression( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(jsonNameArray, 'indexOf'), + [], + [ts.factory.createIdentifier('property')] + ), + ts.SyntaxKind.GreaterThanEqualsToken, + ts.factory.createNumericLiteral('0') + ), + ts.factory.createBlock( + !type.isNullable + ? [ + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + // TypeName.fromJson + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(itemSerializer), + 'fromJson' + ), + [], + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + fieldName + ), + ts.factory.createAsExpression( + ts.factory.createIdentifier('v'), + createStringUnknownMapNode() + ) + ] + ) + ), + ts.factory.createReturnStatement(ts.factory.createTrue()) + ] + : [ + ts.factory.createIfStatement( + ts.factory.createIdentifier('v'), + ts.factory.createBlock([ + assignField( + ts.factory.createNewExpression( + ts.factory.createIdentifier(type.type.symbol.name), + undefined, + [] + ) + ), + ts.factory.createExpressionStatement( + ts.factory.createCallExpression( + // TypeName.fromJson + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(itemSerializer), + 'fromJson' + ), + [], + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + fieldName + ), + ts.factory.createAsExpression( + ts.factory.createIdentifier('v'), + createStringUnknownMapNode() + ) + ] + ) + ) + ]), + ts.factory.createBlock([assignField(ts.factory.createNull())]) + ), + ts.factory.createReturnStatement(ts.factory.createTrue()) + ] + ), + !prop.partialNames + ? undefined + : ts.factory.createBlock([ + // for(const candidate of ["", "core"]) { + // if(candidate.indexOf(property) === 0) { + // if(!this.field) { this.field = new FieldType(); } + // if(this.field.setProperty(property.substring(candidate.length), value)) return true; + // } + // } + ts.factory.createForOfStatement( + undefined, + ts.factory.createVariableDeclarationList( + [ts.factory.createVariableDeclaration('c')], + ts.NodeFlags.Const + ), + jsonNameArray, + ts.factory.createBlock([ + ts.factory.createIfStatement( + ts.factory.createBinaryExpression( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('property'), + 'indexOf' + ), + [], + [ts.factory.createIdentifier('c')] + ), + ts.SyntaxKind.EqualsEqualsEqualsToken, + ts.factory.createNumericLiteral('0') + ), + ts.factory.createBlock( + [ + type.isNullable && + ts.factory.createIfStatement( + ts.factory.createPrefixUnaryExpression( + ts.SyntaxKind.ExclamationToken, + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + fieldName + ) + ), + ts.factory.createBlock([ + assignField( + ts.factory.createNewExpression( + ts.factory.createIdentifier( + type.type!.symbol!.name + ), + [], + [] + ) + ) + ]) + ), + ts.factory.createIfStatement( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(itemSerializer), + 'setProperty' + ), + [], + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + fieldName + ), + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('property'), + 'substring' + ), + [], + [ + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('c'), + 'length' + ) + ] + ), + ts.factory.createIdentifier('v') + ] + ), + ts.factory.createBlock([ + ts.factory.createReturnStatement(ts.factory.createTrue()) + ]) + ) + ].filter(s => !!s) as ts.Statement[] + ) + ) + ]) + ) + ]) + ) + ); + } + + if (caseStatements.length > 0) { + for (let i = 0; i < caseValues.length; i++) { + let caseClause = ts.factory.createCaseClause( + ts.factory.createStringLiteral(caseValues[i]), + // last case gets the statements, others are fall through + i < caseValues.length - 1 ? [] : caseStatements + ); + if (prop.target && i === 0) { + caseClause = ts.addSyntheticLeadingComment( + caseClause, + ts.SyntaxKind.MultiLineCommentTrivia, + `@target ${prop.target}`, + true + ); + } + cases.push(caseClause); + } + } + } + + if (cases.length > 0) { + const switchExpr = ts.factory.createSwitchStatement( + ts.factory.createIdentifier('property'), + ts.factory.createCaseBlock(cases) + ); + statements.unshift(switchExpr); + } + + if (serializable.hasSetPropertyExtension) { + statements.push( + ts.factory.createReturnStatement( + createNodeFromSource(`obj.setProperty(property, v);`, ts.SyntaxKind.CallExpression) + ) + ); + } else { + statements.push(ts.factory.createReturnStatement(ts.factory.createFalse())); + } + + return ts.factory.createBlock(addNewLines(statements)); +} + +export function createSetPropertyMethod( + program: ts.Program, + input: ts.ClassDeclaration, + serializable: JsonSerializable, + importer: (name: string, module: string) => void +) { + const methodDecl = createNodeFromSource( + `public class Serializer { + public static setProperty(obj: ${input.name!.text}, property: string, v: unknown): boolean { + } + }`, + ts.SyntaxKind.MethodDeclaration + ); + return setMethodBody(methodDecl, generateSetPropertyBody(program, serializable, importer)); +} diff --git a/src.compiler/typescript/Serializer.toJson.ts b/src.compiler/typescript/Serializer.toJson.ts new file mode 100644 index 000000000..a3d643b68 --- /dev/null +++ b/src.compiler/typescript/Serializer.toJson.ts @@ -0,0 +1,270 @@ +import * as ts from 'typescript'; +import { + addNewLines, + createNodeFromSource, + setMethodBody, + isPrimitiveType, + hasFlag, + getTypeWithNullableInfo, + isTypedArray, + unwrapArrayItemType, + isMap, + isEnumType +} from '../BuilderHelpers'; +import { findModule, findSerializerModule, isImmutable, JsonProperty, JsonSerializable } from './Serializer.common'; + +function isPrimitiveToJson(type: ts.Type, typeChecker: ts.TypeChecker) { + if (!type) { + return false; + } + + const isArray = isTypedArray(type); + const arrayItemType = unwrapArrayItemType(type, typeChecker); + + if (hasFlag(type, ts.TypeFlags.Unknown)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.Number)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.String)) { + return true; + } + if (hasFlag(type, ts.TypeFlags.Boolean)) { + return true; + } + + if (arrayItemType) { + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Number)) { + return true; + } + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.String)) { + return true; + } + if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Boolean)) { + return true; + } + } else if (type.symbol) { + switch (type.symbol.name) { + case 'Uint8Array': + case 'Uint16Array': + case 'Uint32Array': + case 'Int8Array': + case 'Int16Array': + case 'Int32Array': + case 'Float32Array': + case 'Float64Array': + return true; + } + } + + return false; +} + +function generateToJsonBody( + program: ts.Program, + serializable: JsonSerializable, + importer: (name: string, module: string) => void +) { + const statements: ts.Statement[] = []; + + statements.push( + createNodeFromSource( + ` + if(!obj) { + return null; + } + `, + ts.SyntaxKind.IfStatement + ) + ); + + statements.push( + createNodeFromSource( + ` + const o = new Map(); + `, + ts.SyntaxKind.VariableStatement + ) + ); + + for (let prop of serializable.properties) { + const fieldName = (prop.property.name as ts.Identifier).text; + const jsonName = prop.jsonNames.filter(n => n !== '')[0]; + + if (!jsonName || prop.isReadOnly) { + continue; + } + const typeChecker = program.getTypeChecker(); + const type = getTypeWithNullableInfo(typeChecker, prop.property.type!, false); + const isArray = isTypedArray(type.type!); + + let propertyStatements: ts.Statement[] = []; + + if (isPrimitiveToJson(type.type!, typeChecker)) { + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, obj.${fieldName}); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } else if (isEnumType(type.type!)) { + if (type.isNullable) { + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, obj.${fieldName} as number|null); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } else { + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, obj.${fieldName} as number); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } + } else if (isArray) { + const arrayItemType = unwrapArrayItemType(type.type!, typeChecker)!; + let itemSerializer = arrayItemType.symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(arrayItemType, program.getCompilerOptions())); + if (type.isNullable) { + propertyStatements.push( + createNodeFromSource( + `if(obj.${fieldName} !== null) { + o.set(${JSON.stringify(jsonName)}, obj.${fieldName}?.map(i => ${itemSerializer}.toJson(i))); + }`, + ts.SyntaxKind.IfStatement + ) + ); + } else { + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, obj.${fieldName}.map(i => ${itemSerializer}.toJson(i))); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } + + } else if (isMap(type.type)) { + const mapType = type.type as ts.TypeReference; + if (!isPrimitiveType(mapType.typeArguments![0])) { + throw new Error('only Map maps are supported extend if needed!'); + } + + let serializeBlock: ts.Block; + if (isPrimitiveToJson(mapType.typeArguments![1], typeChecker)) { + serializeBlock = createNodeFromSource( + `{ + const m = new Map(); + o.set(${JSON.stringify(jsonName)}, m); + for(const [k, v] of obj.${fieldName}!) { + m.set(k.toString(), v); + } + }`, ts.SyntaxKind.Block); + } else if (isEnumType(mapType.typeArguments![1])) { + serializeBlock = createNodeFromSource( + `{ + const m = new Map(); + o.set(${JSON.stringify(jsonName)}, m); + for(const [k, v] of obj.${fieldName}!) { + m.set(k.toString(), v as number); + } + }`, ts.SyntaxKind.Block); + } else { + const itemSerializer = mapType.typeArguments![1].symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(mapType.typeArguments![1], program.getCompilerOptions())); + + serializeBlock = createNodeFromSource( + `{ + const m = new Map(); + o.set(${JSON.stringify(jsonName)}, m); + for(const [k, v] of obj.${fieldName}!) { + m.set(k.toString(), ${itemSerializer}.toJson(v)); + } + }`, ts.SyntaxKind.Block); + } + + if (type.isNullable) { + propertyStatements.push(ts.factory.createIfStatement( + ts.factory.createBinaryExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier('obj'), + fieldName + ), + ts.SyntaxKind.ExclamationEqualsEqualsToken, + ts.factory.createNull() + ), + serializeBlock) + ); + } else { + propertyStatements.push(serializeBlock); + } + } else if (isImmutable(type.type)) { + let itemSerializer = type.type.symbol.name; + importer(itemSerializer, findModule(type.type, program.getCompilerOptions())); + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, ${itemSerializer}.toJson(obj.${fieldName})); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } else { + let itemSerializer = type.type.symbol.name + 'Serializer'; + importer(itemSerializer, findSerializerModule(type.type, program.getCompilerOptions())); + propertyStatements.push( + createNodeFromSource( + ` + o.set(${JSON.stringify(jsonName)}, ${itemSerializer}.toJson(obj.${fieldName})); + `, + ts.SyntaxKind.ExpressionStatement + ) + ); + } + + if (prop.target) { + propertyStatements = propertyStatements.map(s => + ts.addSyntheticLeadingComment(s, ts.SyntaxKind.MultiLineCommentTrivia, `@target ${prop.target}`, true) + ); + } + + statements.push(...propertyStatements); + } + + if(serializable.hasToJsonExtension) { + statements.push( createNodeFromSource( + `obj.toJson(o);`, + ts.SyntaxKind.ExpressionStatement + )); + } + + statements.push(ts.factory.createReturnStatement(ts.factory.createIdentifier('o'))); + + return ts.factory.createBlock(addNewLines(statements)); +} + +export function createToJsonMethod( + program: ts.Program, + input: ts.ClassDeclaration, + serializable: JsonSerializable, + importer: (name: string, module: string) => void +) { + const methodDecl = createNodeFromSource( + `public class Serializer { + public static toJson(obj: ${input.name!.text} | null): Map | null { + } + }`, + ts.SyntaxKind.MethodDeclaration + ); + return setMethodBody(methodDecl, generateToJsonBody(program, serializable, importer)); +} diff --git a/src.compiler/typescript/SerializerEmitter.ts b/src.compiler/typescript/SerializerEmitter.ts index 36deb070a..cad7c1c1c 100644 --- a/src.compiler/typescript/SerializerEmitter.ts +++ b/src.compiler/typescript/SerializerEmitter.ts @@ -5,1107 +5,12 @@ import * as path from 'path'; import * as ts from 'typescript'; -import createEmitter from './EmitterBase' -import { addNewLines } from '../BuilderHelpers'; -import { isPrimitiveType } from '../BuilderHelpers'; -import { hasFlag } from '../BuilderHelpers'; -import { getTypeWithNullableInfo } from '../BuilderHelpers'; -import { isTypedArray } from '../BuilderHelpers'; -import { unwrapArrayItemType } from '../BuilderHelpers'; -import { isMap } from '../BuilderHelpers'; -import { isEnumType } from '../BuilderHelpers'; -import { isNumberType } from '../BuilderHelpers'; -import { wrapToNonNull } from '../BuilderHelpers'; +import createEmitter from './EmitterBase'; +import { JsonProperty, JsonSerializable, toImportPath } from './Serializer.common'; +import { createSetPropertyMethod } from './Serializer.setProperty'; +import { createFromJsonMethod } from './Serializer.fromJson'; +import { createToJsonMethod } from './Serializer.toJson'; -interface JsonProperty { - partialNames: boolean; - property: ts.PropertyDeclaration; - jsonNames: string[]; - target?: string; -} - -function isImmutable(type: ts.Type | null): boolean { - if (!type || !type.symbol) { - return false; - } - - const declaration = type.symbol.valueDeclaration; - if (declaration) { - return !!ts.getJSDocTags(declaration).find(t => t.tagName.text === 'json_immutable'); - } - - return false; -} - -function removeExtension(fileName: string) { - return fileName.substring(0, fileName.lastIndexOf('.')); -} - -function toImportPath(fileName: string) { - return "@" + removeExtension(fileName).split('\\').join('/'); -} - -function createStringUnknownMapNode(): ts.TypeNode { - return ts.factory.createTypeReferenceNode('Map', - [ - ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), - ]); -} - - -function findModule(type: ts.Type, options: ts.CompilerOptions) { - if (type.symbol) { - for (const decl of type.symbol.declarations) { - const file = decl.getSourceFile(); - if (file) { - const relative = path.relative( - path.join(path.resolve(options.baseUrl!)), - path.resolve(file.fileName) - ); - return toImportPath(relative); - } - } - - return './' + type.symbol.name; - } - - return ''; -} - -function findSerializerModule(type: ts.Type, options: ts.CompilerOptions) { - let module = findModule(type, options); - const importPath = module.split('/'); - importPath.splice(1, 0, 'generated'); - importPath[importPath.length - 1] = type.symbol!.name + 'Serializer'; - return importPath.join('/'); -} - -// -// fromJson -function generateFromJsonBody(importer: (name: string, module: string) => void) { - importer('JsonHelper', '@src/io/JsonHelper'); - return ts.factory.createBlock(addNewLines([ - ts.factory.createIfStatement( - ts.factory.createPrefixUnaryExpression( - ts.SyntaxKind.ExclamationToken, - ts.factory.createIdentifier('m'), - ), - ts.factory.createBlock([ - ts.factory.createReturnStatement() - ]) - ), - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('JsonHelper'), - 'forEach' - ), - undefined, - [ - ts.factory.createIdentifier('m'), - ts.factory.createArrowFunction( - undefined, - undefined, - [ - ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'v'), - ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'k') - ], - undefined, - ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 'setProperty'), - undefined, - [ - ts.factory.createIdentifier('obj'), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('k'), - 'toLowerCase' - ), - undefined, - [] - ), - ts.factory.createIdentifier('v'), - ] - ) - - ) - ] - ) - ), - ])); -} - -function createFromJsonMethod(input: ts.ClassDeclaration, - importer: (name: string, module: string) => void) { - return ts.factory.createMethodDeclaration( - undefined, - [ - ts.factory.createModifier(ts.SyntaxKind.PublicKeyword), - ts.factory.createModifier(ts.SyntaxKind.StaticKeyword) - ], - undefined, - 'fromJson', - undefined, - undefined, - [ - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'obj', - undefined, - ts.factory.createTypeReferenceNode( - input.name!.text, - undefined - ), - ), - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'm', - undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) - ) - ], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword), - generateFromJsonBody(importer) - ) -} -// -// toJson -function isPrimitiveToJson(type: ts.Type, typeChecker: ts.TypeChecker) { - if (!type) { - return false; - } - - const isArray = isTypedArray(type); - const arrayItemType = unwrapArrayItemType(type, typeChecker); - - if (hasFlag(type, ts.TypeFlags.Unknown)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.Number)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.String)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.Boolean)) { - return "val"; - } - - if (arrayItemType) { - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Number)) { - return true; - } - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.String)) { - return true; - } - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Boolean)) { - return true; - } - } else if (type.symbol) { - switch (type.symbol.name) { - case 'Uint8Array': - case 'Uint16Array': - case 'Uint32Array': - case 'Int8Array': - case 'Int16Array': - case 'Int32Array': - case 'Float32Array': - case 'Float64Array': - return true; - } - } - - return false; -} - -function generateToJsonBody( - program: ts.Program, - propertiesToSerialize: JsonProperty[], - importer: (name: string, module: string) => void) { - - const statements: ts.Statement[] = []; - - statements.push(ts.factory.createIfStatement( - ts.factory.createPrefixUnaryExpression( - ts.SyntaxKind.ExclamationToken, - ts.factory.createIdentifier('obj') - ), - ts.factory.createBlock([ - ts.factory.createReturnStatement(ts.factory.createNull()) - ]) - )) - - statements.push(ts.factory.createVariableStatement( - undefined, - ts.factory.createVariableDeclarationList( - [ - ts.factory.createVariableDeclaration('o', - undefined, - undefined, - ts.factory.createNewExpression(ts.factory.createIdentifier('Map'), - [ - ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), - ], - [] - )) - ], - ts.NodeFlags.Const - ) - )); - - for (let prop of propertiesToSerialize) { - const fieldName = (prop.property.name as ts.Identifier).text; - const jsonName = prop.jsonNames.filter(n => n !== '')[0]; - - if (!jsonName) { - continue; - } - const typeChecker = program.getTypeChecker(); - const type = getTypeWithNullableInfo(typeChecker, prop.property.type!); - const isArray = isTypedArray(type.type!); - - let propertyStatements: ts.Statement[] = []; - - if (isPrimitiveToJson(type.type!, typeChecker)) { - propertyStatements.push(ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ] - ))); - } else if (isEnumType(type.type!)) { - propertyStatements.push(ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createAsExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - type.isNullable - ? ts.factory.createUnionTypeNode([ - ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), - ts.factory.createLiteralTypeNode(ts.factory.createNull()) - ]) - : ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword) - ) - ] - ))); - } else if (isArray) { - const arrayItemType = unwrapArrayItemType(type.type!, typeChecker)!; - let itemSerializer = arrayItemType.symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(arrayItemType, program.getCompilerOptions())); - - propertyStatements.push(ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - 'map' - ), - undefined, - [ - ts.factory.createArrowFunction( - undefined, - undefined, - [ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'i')], - undefined, - ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'toJson'), - undefined, - [ - ts.factory.createIdentifier('i'), - ] - ) - ) - ] - ) - ] - ))); - } - else if (isMap(type.type)) { - const mapType = type.type as ts.TypeReference; - if (!isPrimitiveType(mapType.typeArguments![0])) { - throw new Error('only Map maps are supported extend if needed!'); - } - - let writeValue: ts.Expression; - if (isPrimitiveToJson(mapType.typeArguments![1], typeChecker)) { - writeValue = ts.factory.createIdentifier('v'); - } else if (isEnumType(mapType.typeArguments![1])) { - writeValue = ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword) - ); - } - else { - const itemSerializer = mapType.typeArguments![1].symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(mapType.typeArguments![1], program.getCompilerOptions())); - - writeValue = ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'toJson'), - undefined, - [ - ts.factory.createIdentifier('v'), - ] - ); - } - - propertyStatements.push(ts.factory.createBlock([ - ts.factory.createVariableStatement( - undefined, - ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration('m', - undefined, - undefined, - ts.factory.createNewExpression(ts.factory.createIdentifier('Map'), - [ - ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) - ], - [])) - ], ts.NodeFlags.Const) - ), - ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createIdentifier('m') - ] - )), - - ts.factory.createForOfStatement( - undefined, - ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration( - ts.factory.createArrayBindingPattern([ - ts.factory.createBindingElement( - undefined, - undefined, - 'k' - ), - ts.factory.createBindingElement( - undefined, - undefined, - 'v' - ), - ]) - )], - ts.NodeFlags.Const - ), - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ts.factory.createBlock([ - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('m'), 'set'), - undefined, - [ - // todo: key to string - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('k'), - 'toString' - ), - undefined, - [] - ), - writeValue - ] - ) - ) - ]) - ) - ])); - } else if (isImmutable(type.type)) { - let itemSerializer = type.type.symbol.name; - importer(itemSerializer, findModule(type.type, program.getCompilerOptions())); - propertyStatements.push(ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'toJson'), - [], - [ - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ] - ), - ] - ))); - } else { - let itemSerializer = type.type.symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(type.type, program.getCompilerOptions())); - propertyStatements.push(ts.factory.createExpressionStatement(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('o'), 'set'), - undefined, - [ - ts.factory.createStringLiteral(jsonName), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'toJson'), - [], - [ - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ] - ), - ] - ))); - } - - if (prop.target) { - propertyStatements = propertyStatements.map(s => ts.addSyntheticLeadingComment(s, ts.SyntaxKind.MultiLineCommentTrivia, `@target ${prop.target}`, true)); - } - - statements.push(...propertyStatements); - } - - statements.push(ts.factory.createReturnStatement(ts.factory.createIdentifier('o'))); - - return ts.factory.createBlock(addNewLines(statements)) -} - -function createToJsonMethod(program: ts.Program, - input: ts.ClassDeclaration, - propertiesToSerialize: JsonProperty[], - importer: (name: string, module: string) => void -) { - return ts.factory.createMethodDeclaration( - undefined, - [ - ts.factory.createModifier(ts.SyntaxKind.PublicKeyword), - ts.factory.createModifier(ts.SyntaxKind.StaticKeyword) - ], - undefined, - 'toJson', - undefined, - undefined, - [ - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'obj', - undefined, - ts.factory.createUnionTypeNode([ - ts.factory.createTypeReferenceNode( - input.name!.text, - undefined - ), - ts.factory.createLiteralTypeNode(ts.factory.createNull()) - ]) - ) - ], - ts.factory.createUnionTypeNode([ - createStringUnknownMapNode(), - ts.factory.createLiteralTypeNode(ts.factory.createNull()) - ]), - generateToJsonBody(program, propertiesToSerialize, importer) - ) -} - -// -// setProperty - -function isPrimitiveFromJson(type: ts.Type, typeChecker: ts.TypeChecker) { - if (!type) { - return false; - } - - const isArray = isTypedArray(type); - const arrayItemType = unwrapArrayItemType(type, typeChecker); - - if (hasFlag(type, ts.TypeFlags.Unknown)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.Number)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.String)) { - return true; - } - if (hasFlag(type, ts.TypeFlags.Boolean)) { - return true; - } - - if (arrayItemType) { - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Number)) { - return true; - } - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.String)) { - return true; - } - if (isArray && hasFlag(arrayItemType, ts.TypeFlags.Boolean)) { - return true; - } - } else if (type.symbol) { - switch (type.symbol.name) { - case 'Uint8Array': - case 'Uint16Array': - case 'Uint32Array': - case 'Int8Array': - case 'Int16Array': - case 'Int32Array': - case 'Float32Array': - case 'Float64Array': - return true; - } - } - - return null; - -} - -function createEnumMapping(type: ts.Type): ts.Expression { - return ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('JsonHelper'), - 'parseEnum' - ), - [ts.factory.createTypeReferenceNode(type.symbol.name)], - [ - ts.factory.createIdentifier('v'), - ts.factory.createIdentifier(type.symbol.name) - ] - ); -} - -function stripRanges(node: T) { - (node as any).pos = -1; - (node as any).end = -1; - return node; -} - -function getDeepMutableClone(node: T): T { - return ts.transform(node, [ - context => node => deepCloneWithContext(node, context) - ]).transformed[0]; - - function deepCloneWithContext( - node: T, - context: ts.TransformationContext - ): T { - const clonedNode = ts.visitEachChild( - stripRanges(ts.getMutableClone(node)), - child => deepCloneWithContext(child, context), - context - ); - (clonedNode as any).parent = undefined as any; - ts.forEachChild(clonedNode, child => { (child as any).parent = clonedNode; }); - return clonedNode; - } -} - - -function generateSetPropertyBody(program: ts.Program, - propertiesToSerialize: JsonProperty[], - importer: (name: string, module: string) => void -) { - const statements: ts.Statement[] = []; - const cases: ts.CaseOrDefaultClause[] = []; - - const typeChecker = program.getTypeChecker(); - for (const prop of propertiesToSerialize) { - const jsonNames = prop.jsonNames.map(j => j.toLowerCase()); - const caseValues: string[] = jsonNames.filter(j => j !== ''); - const fieldName = (prop.property.name as ts.Identifier).text; - - const caseStatements: ts.Statement[] = []; - - const type = getTypeWithNullableInfo(typeChecker, prop.property.type); - - const assignField = function (expr: ts.Expression): ts.Statement { - return ts.factory.createExpressionStatement( - ts.factory.createAssignment(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), expr) - ); - }; - - if (isPrimitiveFromJson(type.type!, typeChecker)) { - caseStatements.push(assignField(ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - getDeepMutableClone(prop.property.type!) - ))); - caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); - } else if (isEnumType(type.type)) { - // obj.fieldName = enummapping - // return true; - importer(type.type.symbol!.name, findModule(type.type, program.getCompilerOptions())); - importer('JsonHelper', '@src/io/JsonHelper'); - const read = createEnumMapping(type.type); - if (type.isNullable) { - caseStatements.push(assignField(read)); - } else { - caseStatements.push(assignField(ts.factory.createNonNullExpression(read))); - } - caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); - } else if (isTypedArray(type.type!)) { - const arrayItemType = unwrapArrayItemType(type.type!, typeChecker)!; - const collectionAddMethod = ts.getJSDocTags(prop.property) - .filter(t => t.tagName.text === 'json_add') - .map(t => t.comment ?? "")[0]; - - // obj.fieldName = []; - // for(const i of value) { - // obj.addFieldName(Type.FromJson(i)); - // } - // or - // for(const __li of value) { - // obj.fieldName.push(Type.FromJson(__li)); - // } - - let itemSerializer = arrayItemType.symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(arrayItemType, program.getCompilerOptions())); - importer(arrayItemType.symbol.name, findModule(arrayItemType, program.getCompilerOptions())); - - const loopItems = [ - assignField(ts.factory.createArrayLiteralExpression(undefined)), - ts.factory.createForOfStatement( - undefined, - ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration('o')], ts.NodeFlags.Const), - ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - ts.factory.createArrayTypeNode( - ts.factory.createUnionTypeNode([ - createStringUnknownMapNode(), - ts.factory.createLiteralTypeNode(ts.factory.createNull()) - ]) - ) - ), - ts.factory.createBlock([ - ts.factory.createVariableStatement( - undefined, - ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration('i', - undefined, - undefined, - ts.factory.createNewExpression( - ts.factory.createIdentifier(arrayItemType.symbol.name), - undefined, - [] - )) - ], ts.NodeFlags.Const) - ), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'fromJson'), - undefined, - [ - ts.factory.createIdentifier('i'), - ts.factory.createIdentifier('o') - ] - ), - ts.factory.createExpressionStatement( - collectionAddMethod - // obj.addFieldName(i) - ? ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('obj'), - collectionAddMethod - ), - undefined, - [ts.factory.createIdentifier('i')] - ) - // obj.fieldName.push(i) - : ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('obj'), - fieldName - ), - 'push' - ), - undefined, - [ts.factory.createIdentifier('i')] - ) - ) - ].filter(s => !!s) as ts.Statement[]) - ), - ]; - - if (type.isNullable) { - caseStatements.push(ts.factory.createIfStatement( - ts.factory.createIdentifier('v'), - ts.factory.createBlock(loopItems) - )); - } else { - caseStatements.push(...loopItems); - } - caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); - - } else if (isMap(type.type)) { - const mapType = type.type as ts.TypeReference; - if (!isPrimitiveType(mapType.typeArguments![0])) { - throw new Error('only Map maps are supported extend if needed!'); - } - - let mapKey; - if (isEnumType(mapType.typeArguments![0])) { - importer(mapType.typeArguments![0].symbol!.name, findModule(mapType.typeArguments![0], program.getCompilerOptions())); - importer('JsonHelper', '@src/io/JsonHelper'); - mapKey = ts.factory.createNonNullExpression(ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('JsonHelper'), 'parseEnum'), - [ts.factory.createTypeReferenceNode(mapType.typeArguments![0].symbol!.name)], - [ - ts.factory.createIdentifier('k'), - ts.factory.createIdentifier(mapType.typeArguments![0].symbol!.name), - ] - )); - } else if (isNumberType(mapType.typeArguments![0])) { - mapKey = ts.factory.createCallExpression( - ts.factory.createIdentifier('parseInt'), - undefined, - [ - ts.factory.createIdentifier('k') - ] - ); - } else { - mapKey = ts.factory.createIdentifier('k'); - } - - let mapValue; - let itemSerializer: string = ''; - if (isPrimitiveFromJson(mapType.typeArguments![1], typeChecker)) { - // const isNullable = mapType.typeArguments![1].flags & ts.TypeFlags.Union - // && !!(mapType.typeArguments![1] as ts.UnionType).types.find(t => t.flags & ts.TypeFlags.Null); - - mapValue = ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - ts.isTypeReferenceNode(prop.property.type!) && prop.property.type.typeArguments - ? getDeepMutableClone(prop.property.type.typeArguments[1]) - : ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) - ); - } else { - itemSerializer = mapType.typeArguments![1].symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(mapType.typeArguments![1], program.getCompilerOptions())); - importer(mapType.typeArguments![1]!.symbol.name, findModule(mapType.typeArguments![1], program.getCompilerOptions())); - mapValue = ts.factory.createIdentifier('i'); - } - - const collectionAddMethod = ts.getJSDocTags(prop.property) - .filter(t => t.tagName.text === 'json_add') - .map(t => t.comment ?? "")[0]; - - caseStatements.push(assignField(ts.factory.createNewExpression(ts.factory.createIdentifier('Map'), [ - typeChecker.typeToTypeNode(mapType.typeArguments![0], undefined, undefined)!, - typeChecker.typeToTypeNode(mapType.typeArguments![1], undefined, undefined)!, - ], []))); - - caseStatements.push( - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('JsonHelper'), - 'forEach' - ), - undefined, - [ - ts.factory.createIdentifier('v'), - ts.factory.createArrowFunction( - undefined, - undefined, - [ - ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'v'), - ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'k') - ], - undefined, - ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), - ts.factory.createBlock(addNewLines([ - itemSerializer.length > 0 && ts.factory.createVariableStatement( - undefined, - ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration('i', - undefined, undefined, - ts.factory.createNewExpression(ts.factory.createIdentifier(mapType.typeArguments![1].symbol.name), undefined, []) - ) - ], ts.NodeFlags.Const), - ), - itemSerializer.length > 0 && ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(itemSerializer), - 'fromJson' - ), - undefined, - [ - ts.factory.createIdentifier('i'), - ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - createStringUnknownMapNode() - ), - ] - ) - ), - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - collectionAddMethod - ? ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), collectionAddMethod) - : ts.factory.createPropertyAccessExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), ts.factory.createIdentifier(fieldName)), - ts.factory.createIdentifier('set') - ), - undefined, - [ - mapKey, - mapValue - ] - ) - ) - ].filter(s => !!s) as ts.Statement[])) - ) - ] - ) - ) - ); - - caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); - } else if (isImmutable(type.type)) { - let itemSerializer = type.type.symbol.name; - importer(itemSerializer, findModule(type.type, program.getCompilerOptions())); - - // obj.fieldName = TypeName.fromJson(value)! - // return true; - caseStatements.push( - assignField( - wrapToNonNull( - type.isNullable, - ts.factory.createCallExpression( - // TypeName.fromJson - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'fromJson'), - [], - [ - ts.factory.createIdentifier('v') - ] - ), - ts.factory - ) - ) - ); - caseStatements.push(ts.factory.createReturnStatement(ts.factory.createTrue())); - } else { - // for complex types it is a bit more tricky - // if the property matches exactly, we use fromJson - // if the property starts with the field name, we try to set a sub-property - const jsonNameArray = ts.factory.createArrayLiteralExpression(jsonNames.map(n => ts.factory.createStringLiteral(n))); - - let itemSerializer = type.type.symbol.name + "Serializer"; - importer(itemSerializer, findSerializerModule(type.type, program.getCompilerOptions())); - if (type.isNullable) { - importer(type.type.symbol!.name, findModule(type.type, program.getCompilerOptions())); - } - - // TODO if no partial name support, simply generate cases - statements.push( - ts.factory.createIfStatement( - // if(["", "core"].indexOf(property) >= 0) - ts.factory.createBinaryExpression( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(jsonNameArray, 'indexOf'), - [], - [ts.factory.createIdentifier('property')] - ), - ts.SyntaxKind.GreaterThanEqualsToken, - ts.factory.createNumericLiteral('0') - ), - ts.factory.createBlock( - !type.isNullable - ? [ - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - // TypeName.fromJson - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'fromJson'), - [], - [ - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - createStringUnknownMapNode() - ) - ] - ) - ), - ts.factory.createReturnStatement(ts.factory.createTrue()) - ] - : [ - ts.factory.createIfStatement( - ts.factory.createIdentifier('v'), - ts.factory.createBlock([ - assignField(ts.factory.createNewExpression( - ts.factory.createIdentifier(type.type.symbol.name), - undefined, - [] - )), - ts.factory.createExpressionStatement( - ts.factory.createCallExpression( - // TypeName.fromJson - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(itemSerializer), 'fromJson'), - [], - [ - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ts.factory.createAsExpression( - ts.factory.createIdentifier('v'), - createStringUnknownMapNode() - ) - ] - ) - ) - ]), - ts.factory.createBlock([ - assignField(ts.factory.createNull()) - ]) - ), - ts.factory.createReturnStatement(ts.factory.createTrue()) - ]), - !prop.partialNames ? undefined : - ts.factory.createBlock([ - // for(const candidate of ["", "core"]) { - // if(candidate.indexOf(property) === 0) { - // if(!this.field) { this.field = new FieldType(); } - // if(this.field.setProperty(property.substring(candidate.length), value)) return true; - // } - // } - ts.factory.createForOfStatement( - undefined, - ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration('c')], ts.NodeFlags.Const), - jsonNameArray, - ts.factory.createBlock([ - ts.factory.createIfStatement( - ts.factory.createBinaryExpression( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('property'), 'indexOf'), - [], - [ts.factory.createIdentifier('c')] - ), - ts.SyntaxKind.EqualsEqualsEqualsToken, - ts.factory.createNumericLiteral('0') - ), - ts.factory.createBlock([ - type.isNullable && ts.factory.createIfStatement( - ts.factory.createPrefixUnaryExpression( - ts.SyntaxKind.ExclamationToken, - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName) - ), - ts.factory.createBlock([ - assignField(ts.factory.createNewExpression(ts.factory.createIdentifier(type.type!.symbol!.name), [], [])) - ]) - ), - ts.factory.createIfStatement( - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(itemSerializer), - 'setProperty' - ), - [], - [ - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('obj'), fieldName), - ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier('property'), - 'substring' - ), - [], - [ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('c'), 'length')] - ), - ts.factory.createIdentifier('v') - ] - ), - ts.factory.createBlock([ - ts.factory.createReturnStatement(ts.factory.createTrue()) - ]) - ) - ].filter(s => !!s) as ts.Statement[]) - ) - ]) - ) - ]) - ) - ); - } - - if (caseStatements.length > 0) { - for (let i = 0; i < caseValues.length; i++) { - let caseClause = ts.factory.createCaseClause( - ts.factory.createStringLiteral(caseValues[i]), - // last case gets the statements, others are fall through - i < caseValues.length - 1 ? [] : caseStatements - ); - if (prop.target && i === 0) { - caseClause = ts.addSyntheticLeadingComment(caseClause, ts.SyntaxKind.MultiLineCommentTrivia, `@target ${prop.target}`, true); - } - cases.push(caseClause); - } - } - } - - if (cases.length > 0) { - const switchExpr = ts.factory.createSwitchStatement(ts.factory.createIdentifier('property'), ts.factory.createCaseBlock(cases)); - statements.unshift(switchExpr); - } - - statements.push(ts.factory.createReturnStatement(ts.factory.createFalse())); - - return ts.factory.createBlock(addNewLines(statements)); -} - -function createSetPropertyMethod( - program: ts.Program, - input: ts.ClassDeclaration, - propertiesToSerialize: JsonProperty[], - importer: (name: string, module: string) => void -) { - return ts.factory.createMethodDeclaration( - undefined, - [ - ts.factory.createModifier(ts.SyntaxKind.PublicKeyword), - ts.factory.createModifier(ts.SyntaxKind.StaticKeyword) - ], - undefined, - 'setProperty', - undefined, - undefined, - [ - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'obj', - undefined, - ts.factory.createTypeReferenceNode( - input.name!.text, - undefined - ) - ), - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'property', - undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword) - ), - ts.factory.createParameterDeclaration( - undefined, - undefined, - undefined, - 'v', - undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) - ) - ], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), - generateSetPropertyBody(program, propertiesToSerialize, importer) - ) -} export default createEmitter('json', (program, input) => { console.log(`Writing Serializer for ${input.name!.text}`); @@ -1114,29 +19,48 @@ export default createEmitter('json', (program, input) => { path.resolve(input.getSourceFile().fileName) ); - let propertiesToSerialize: JsonProperty[] = []; + const serializable: JsonSerializable = { + properties: [], + isStrict: !!ts.getJSDocTags(input).find(t => t.tagName.text === 'json_strict'), + hasToJsonExtension: false, + hasSetPropertyExtension: false + }; + input.members.forEach(member => { if (ts.isPropertyDeclaration(member)) { const propertyDeclaration = member as ts.PropertyDeclaration; - if (!propertyDeclaration.modifiers!.find(m => - m.kind === ts.SyntaxKind.StaticKeyword || - m.kind === ts.SyntaxKind.PrivateKeyword)) { - const jsonNames = [(member.name as ts.Identifier).text]; + if ( + !propertyDeclaration.modifiers!.find( + m => m.kind === ts.SyntaxKind.StaticKeyword || m.kind === ts.SyntaxKind.PrivateKeyword + ) + ) { + const jsonNames = [(member.name as ts.Identifier).text.toLowerCase()]; if (ts.getJSDocTags(member).find(t => t.tagName.text === 'json_on_parent')) { jsonNames.push(''); } if (!ts.getJSDocTags(member).find(t => t.tagName.text === 'json_ignore')) { - propertiesToSerialize.push({ + serializable.properties.push({ property: propertyDeclaration, jsonNames: jsonNames, partialNames: !!ts.getJSDocTags(member).find(t => t.tagName.text === 'json_partial_names'), - target: ts.getJSDocTags(member).find(t => t.tagName.text === 'target')?.comment + target: ts.getJSDocTags(member).find(t => t.tagName.text === 'target')?.comment as string, + isReadOnly: !!ts.getJSDocTags(member).find(t => t.tagName.text === 'json_read_only') }); } } } + else if (ts.isMethodDeclaration(member)) { + switch ((member.name as ts.Identifier).text) { + case 'toJson': + serializable.hasToJsonExtension = true; + break; + case 'setProperty': + serializable.hasSetPropertyExtension = true; + break; + } + } }); const statements: ts.Statement[] = []; @@ -1147,51 +71,56 @@ export default createEmitter('json', (program, input) => { return; } importedNames.add(name); - statements.push(ts.factory.createImportDeclaration( - undefined, - undefined, - ts.factory.createImportClause( - false, + statements.push( + ts.factory.createImportDeclaration( undefined, - ts.factory.createNamedImports([ts.factory.createImportSpecifier( + undefined, + ts.factory.createImportClause( + false, undefined, - ts.factory.createIdentifier(name) - )]) - ), - ts.factory.createStringLiteral(module) - )) + ts.factory.createNamedImports([ + ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name)) + ]) + ), + ts.factory.createStringLiteral(module) + ) + ); } - statements.push(ts.factory.createClassDeclaration( - [], - [ - ts.factory.createModifier(ts.SyntaxKind.ExportKeyword), - ], - input.name!.text + 'Serializer', - undefined, - undefined, - [ - createFromJsonMethod(input, importer), - createToJsonMethod(program, input, propertiesToSerialize, importer), - createSetPropertyMethod(program, input, propertiesToSerialize, importer) - ] - )); - - const sourceFile = ts.factory.createSourceFile([ - ts.factory.createImportDeclaration( + statements.push( + ts.factory.createClassDeclaration( + [], + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + input.name!.text + 'Serializer', undefined, undefined, - ts.factory.createImportClause(false, + [ + createFromJsonMethod(input, serializable, importer), + createToJsonMethod(program, input, serializable, importer), + createSetPropertyMethod(program, input, serializable, importer) + ] + ) + ); + + const sourceFile = ts.factory.createSourceFile( + [ + ts.factory.createImportDeclaration( + undefined, undefined, - ts.factory.createNamedImports([ts.factory.createImportSpecifier( + ts.factory.createImportClause( + false, undefined, - ts.factory.createIdentifier(input.name!.text) - )]) + ts.factory.createNamedImports([ + ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(input.name!.text)) + ]) + ), + ts.factory.createStringLiteral(toImportPath(sourceFileName)) ), - ts.factory.createStringLiteral(toImportPath(sourceFileName)) - ), - ...statements - ], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None); + ...statements + ], + ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), + ts.NodeFlags.None + ); return sourceFile; -}); \ No newline at end of file +}); diff --git a/src.csharp/AlphaTab.Test/AlphaTab.Test.csproj b/src.csharp/AlphaTab.Test/AlphaTab.Test.csproj index 74b41307b..feb27f548 100644 --- a/src.csharp/AlphaTab.Test/AlphaTab.Test.csproj +++ b/src.csharp/AlphaTab.Test/AlphaTab.Test.csproj @@ -2,7 +2,7 @@ AlphaTab - netcoreapp3.1 + net6.0 false enable 8 @@ -11,10 +11,9 @@ - - - - + + + @@ -25,6 +24,10 @@ test-data\%(RecursiveDir)\%(Filename)%(Extension) PreserveNewest + + font\%(RecursiveDir)\%(Filename)%(Extension) + PreserveNewest + diff --git a/src.csharp/AlphaTab.Test/Model/ComparisonHelpers.cs b/src.csharp/AlphaTab.Test/Model/ComparisonHelpers.cs new file mode 100644 index 000000000..61ab527d4 --- /dev/null +++ b/src.csharp/AlphaTab.Test/Model/ComparisonHelpers.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using AlphaTab.Test; + +namespace AlphaTab.Model +{ + internal partial class ComparisonHelpers + { + private static bool CompareObjects(object? expected, object? actual, string path, + IList ignoreKeys) + { + Globals.Fail( + $"cannot compare unknown object types expected[{actual?.GetType().FullName}] expected[${expected?.GetType().FullName}]"); + return false; + } + } +} diff --git a/src.csharp/AlphaTab.Test/Test/Globals.cs b/src.csharp/AlphaTab.Test/Test/Globals.cs index 427376b4a..05660269e 100644 --- a/src.csharp/AlphaTab.Test/Test/Globals.cs +++ b/src.csharp/AlphaTab.Test/Test/Globals.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AlphaTab.Test @@ -10,6 +10,11 @@ public static Expector Expect(T actual) return new Expector(actual); } + public static Expector Expect(Action actual) + { + return new Expector(actual); + } + public static void Fail(object? message) { Assert.Fail(Convert.ToString(message)); @@ -84,5 +89,29 @@ public void ToBeFalsy() { Assert.AreEqual(default!, _actual, _message); } + + public void ToThrowError(Type expected) + { + if (_actual is Action d) + { + try + { + d(); + Assert.Fail("Did not throw error:" + _message); + } + catch (Exception e) + { + if (expected.IsInstanceOfType(e)) + { + return; + } + } + Assert.Fail("Exception type didn't match:" + _message); + } + else + { + Assert.Fail("ToThrowError can only be used with an exception:" + _message); + } + } } } diff --git a/src.csharp/AlphaTab.Test/TestPlatform.cs b/src.csharp/AlphaTab.Test/TestPlatform.cs index 6582ca651..d24832dd3 100644 --- a/src.csharp/AlphaTab.Test/TestPlatform.cs +++ b/src.csharp/AlphaTab.Test/TestPlatform.cs @@ -19,7 +19,7 @@ public static async Task LoadFile(string path) public static async Task SaveFile(string name, Uint8Array data) { var path = Path.Combine("test-results", name); - Directory.CreateDirectory(Path.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)!); await using var fs = new FileStream(Path.Combine("test-results", name), FileMode.Create); await fs.WriteAsync(data.Data.Array!, data.Data.Offset, data.Data.Count); } diff --git a/src.csharp/AlphaTab.Test/VisualTests/PixelMatch.cs b/src.csharp/AlphaTab.Test/VisualTests/PixelMatch.cs deleted file mode 100644 index 4406a5e14..000000000 --- a/src.csharp/AlphaTab.Test/VisualTests/PixelMatch.cs +++ /dev/null @@ -1,326 +0,0 @@ -using System; -using System.Data; -using SkiaSharp; - -namespace AlphaTab.VisualTests -{ - // Based on MapBox PixelMatch: https://github.com/mapbox/pixelmatch - - // ISC License - - // Copyright(c) 2018, Mapbox - - // Permission to use, copy, modify, and/or distribute this software for any purpose - // with or without fee is hereby granted, provided that the above copyright notice - // and this permission notice appear in all copies. - - - // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - // FITNESS.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - // OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - // THIS SOFTWARE. - - internal class PixelMatch - { - public static unsafe PixelMatchResult Run(SKBitmap img1, SKBitmap img2, - PixelMatchOptions options) - { - var result = new PixelMatchResult(); - - if (img1.Width == img2.Width && img1.Height == img2.Height) - { - result.SizesMatch = true; - } - else - { - result.SizesMatch = false; - return result; - } - - var threshold = options.Threshold; - // maximum acceptable square distance between two colors; - // 35215 is the maximum possible value for the YIQ difference metric - var maxDelta = 35215 * threshold * threshold; - var diff = 0; - - var width = img1.Width; - var height = img1.Height; - - var img1Raw = (byte*) img1.GetPixels().ToPointer(); - var img2Raw = (byte*) img2.GetPixels().ToPointer(); - byte* outputRaw = null; - - // compare each pixel of one image against the other one - if (options.CreateOutputImage) - { - result.Output = - new SKBitmap(new SKImageInfo(width, height, SKImageInfo.PlatformColorType, - SKAlphaType.Premul)); - outputRaw = (byte*) result.Output.GetPixels().ToPointer(); - } - - var totalPixels = 0; - - for (var y = 0; y < height; y++) - { - for (var x = 0; x < width; x++) - { - var pos = (y * width + x) * 4; - // squared YUV distance between colors at this pixel position - var delta = ColorDelta(img1Raw, img2Raw, pos, pos, false, - out var wasTransparent); - - if (wasTransparent && options.IgnoreTransparent) - { - continue; - } - - totalPixels++; - - // the color difference is above the threshold - if (delta > maxDelta) - { - // check it's a real rendering difference or just anti-aliasing - if (!options.IncludeAntiAlias && - (AntiAliased(img1Raw, x, y, width, height, img2Raw) || - AntiAliased(img2Raw, x, y, width, height, img1Raw))) - { - // one of the pixels is anti-aliasing; draw as yellow and do not count as difference - if (options.CreateOutputImage) - { - DrawPixel(outputRaw, pos, 255, 255, 0); - } - } - else - { - // found substantial difference not caused by anti-aliasing; draw it as red - if (options.CreateOutputImage) - { - DrawPixel(outputRaw, pos, 255, 0, 0); - } - - diff++; - } - } - else if (options.CreateOutputImage) - { - // pixels are similar; draw background as grayscale image blended with white - var val = (byte) Blend(GrayPixel(img1Raw, pos), 0.1); - DrawPixel(outputRaw, pos, val, val, val); - } - } - } - - result.DifferentPixels = diff; - result.TotalPixels = totalPixels; - return result; - } - - private static unsafe bool AntiAliased(byte* img, int x1, int y1, int width, int height, - byte* img2 = null) - { - var x0 = Math.Max(x1 - 1, 0); - var y0 = Math.Max(y1 - 1, 0); - var x2 = Math.Min(x1 + 1, width - 1); - var y2 = Math.Min(y1 + 1, height - 1); - var pos = (y1 * width + x1) * 4; - var zeroes = 0; - double min = 0; - double max = 0; - - var minX = 0; - var minY = 0; - var maxX = 0; - var maxY = 0; - - // go through 8 adjacent pixels - for (var x = x0; x <= x2; x++) - { - for (var y = y0; y <= y2; y++) - { - if (x == x1 && y == y1) - { - continue; - } - - // brightness delta between the center pixel and adjacent one - var delta = ColorDelta(img, img, pos, (y * width + x) * 4, true, - out var wasTransparent); - - // count the number of equal, darker and brighter adjacent pixels - if (delta == 0) - { - zeroes++; - // if found more than 2 equal siblings, it's definitely not anti-aliasing - if (zeroes > 2) - { - return false; - } - } - // remember darkest pixel - else if (delta < min) - { - min = delta; - minX = x; - minY = y; - } - // remember the brightest pixel - else if (delta > max) - { - max = delta; - maxX = x; - maxY = y; - } - } - } - - // if there are no both darker and brighter pixels among siblings, it's not anti-aliasing - if (min == 0 || max == 0) - { - return false; - } - - // if either the darkest or the brightest pixel has more than 2 equal siblings in both images - // (definitely not anti-aliased), this pixel is anti-aliased - return (HasManySiblings(img, minX, minY, width, height) && - HasManySiblings(img2, minX, minY, width, height)) || - (HasManySiblings(img, maxX, maxY, width, height) && - HasManySiblings(img2, maxX, maxY, width, height)); - } - - // check if a pixel has 3+ adjacent pixels of the same color. - private static unsafe bool HasManySiblings(byte* img, int x1, int y1, int width, int height) - { - var x0 = Math.Max(x1 - 1, 0); - var y0 = Math.Max(y1 - 1, 0); - var x2 = Math.Min(x1 + 1, width - 1); - var y2 = Math.Min(y1 + 1, height - 1); - var pos = (y1 * width + x1) * 4; - var zeroes = x1 == x0 || x1 == x2 || y1 == y0 || y1 == y2 ? 1 : 0; - - // go through 8 adjacent pixels - for (var x = x0; x <= x2; x++) - { - for (var y = y0; y <= y2; y++) - { - if (x == x1 && y == y1) continue; - - var pos2 = (y * width + x) * 4; - if (img[pos] == img[pos2] && - img[pos + 1] == img[pos2 + 1] && - img[pos + 2] == img[pos2 + 2] && - img[pos + 3] == - img[pos2 + 3]) zeroes++; - - if (zeroes > 2) return true; - } - } - - return false; - } - - private static unsafe byte GrayPixel(byte* img, int i) - { - var a = img[i + 3] / 255; - var r = Blend(img[i + 0], a); - var g = Blend(img[i + 1], a); - var b = Blend(img[i + 2], a); - return (byte) Rgb2Y(r, g, b); - } - - private static unsafe void DrawPixel(byte* outputRaw, int pos, byte r, byte g, byte b) - { - outputRaw[pos + 0] = r; - outputRaw[pos + 1] = g; - outputRaw[pos + 2] = b; - outputRaw[pos + 3] = 255; - } - - private static unsafe double ColorDelta(byte* img1, byte* img2, int k, int m, bool yOnly, - out bool wasTransparent) - { - double r1 = img1[k + 0]; - double g1 = img1[k + 1]; - double b1 = img1[k + 2]; - double a1 = img1[k + 3]; - - double r2 = img2[m + 0]; - double g2 = img2[m + 1]; - double b2 = img2[m + 2]; - double a2 = img2[m + 3]; - - wasTransparent = Math.Abs(a1) < 0.01 && Math.Abs(a2) < 0.01; - - if (a1 == a2 && r1 == r2 && g1 == g2 && b1 == b2) return 0; - - if (a1 < 255) { - a1 /= 255; - r1 = Blend(r1, a1); - g1 = Blend(g1, a1); - b1 = Blend(b1, a1); - } - - if (a2 < 255) { - a2 /= 255; - r2 = Blend(r2, a2); - g2 = Blend(g2, a2); - b2 = Blend(b2, a2); - } - - var y = Rgb2Y(r1, g1, b1) - Rgb2Y(r2, g2, b2); - - if (yOnly) return y; // brightness difference only - - var i = Rgb2I(r1, g1, b1) - Rgb2I(r2, g2, b2); - var q = Rgb2Q(r1, g1, b1) - Rgb2Q(r2, g2, b2); - - return 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q; - } - - private static double Rgb2Q(double r, double g, double b) - { - return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; - } - - private static double Rgb2I(double r, double g, double b) - { - return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; - } - - private static double Rgb2Y(double r, double g, double b) - { - return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; - } - - private static double Blend(double c, double a) - { - return 255 + (c - 255) * a; - } - } - - internal class PixelMatchOptions - { - public double Threshold { get; set; } - public bool IncludeAntiAlias { get; set; } - - public bool CreateOutputImage { get; set; } - public bool IgnoreTransparent { get; set; } - - public PixelMatchOptions() - { - Threshold = 0.1; - } - } - - internal class PixelMatchResult - { - public SKBitmap? Output { get; set; } - public int DifferentPixels { get; set; } - public int TotalPixels { get; set; } - public double Mismatch => DifferentPixels / (double) TotalPixels; - public bool SizesMatch { get; set; } - } -} diff --git a/src.csharp/AlphaTab.Test/VisualTests/VisualTestHelper.cs b/src.csharp/AlphaTab.Test/VisualTests/VisualTestHelper.cs index bc5d299e4..38423e250 100644 --- a/src.csharp/AlphaTab.Test/VisualTests/VisualTestHelper.cs +++ b/src.csharp/AlphaTab.Test/VisualTests/VisualTestHelper.cs @@ -1,125 +1,97 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using AlphaTab.Core; using AlphaTab.Core.EcmaScript; -using AlphaTab.Importer; -using AlphaTab.Io; using AlphaTab.Model; +using AlphaTab.Platform.CSharp; using AlphaTab.Rendering; using Microsoft.VisualStudio.TestTools.UnitTesting; using SkiaSharp; namespace AlphaTab.VisualTests { - public class VisualTestHelper + partial class VisualTestHelper { - public static async Task RunVisualTest(string inputFile, Settings? settings = null, - IList? tracks = null, string? message = null) + private static async Task RunVisualTestScoreWithResize(Score score, IList widths, + IList referenceImages, Settings? settings, IList? tracks, string? message, + double tolerancePercent) { - try - { - inputFile = $"test-data/visual-tests/{inputFile}"; - var inputFileData = - await TestPlatform.LoadFile(inputFile); - var referenceFileName = TestPlatform.ChangeExtension(inputFile, ".png"); - var score = ScoreLoader.LoadScoreFromBytes(inputFileData, settings); - - await VisualTestHelper.RunVisualTestScore(score, referenceFileName, settings, - tracks, message); - } - catch (Exception e) - { - Assert.Fail($"Failed to run visual test {e}"); - } - } + tracks ??= new List { 0 }; + PrepareSettingsForTest(ref settings); - public static async Task RunVisualTestTex(string tex, string referenceFileName, - Settings? settings = null, - IList? tracks = null, string? message = null) - { - try + var referenceFileData = new List(); + foreach (var referenceFileName in referenceImages) { - if (settings == null) + if (referenceFileName == null) { - settings = new Settings(); + referenceFileData.Add(null); + } + else + { + referenceFileData.Add(await TestPlatform.LoadFile(Path.Combine("test-data", "visual-tests", referenceFileName))); } - - var importer = new AlphaTexImporter(); - importer.Init(ByteBuffer.FromString(tex), settings); - var score = importer.ReadScore(); - - await VisualTestHelper.RunVisualTestScore(score, referenceFileName, settings, - tracks, message); - } - catch (Exception e) - { - Assert.Fail($"Failed to run visual test {e}"); - } - } - - public static async Task RunVisualTestScore(Score score, string referenceFileName, - Settings? settings = null, - IList? tracks = null, string? message = null) - { - if (settings == null) - { - settings = new Settings(); } - if (tracks == null) - { - tracks = new List {0}; - } - - settings.Core.Engine = "skia"; - settings.Core.EnableLazyLoading = false; - settings.Core.UseWorkers = false; - - if(!referenceFileName.StartsWith("test-data/")) { - referenceFileName = $"test-data/visual-tests/{referenceFileName}"; - } - - var referenceFileData = - await TestPlatform.LoadFile(referenceFileName); - - var result = new List(); - var totalWidth = 0.0; - var totalHeight = 0.0; + var results = new List>(); + var totalWidths = new List(); + var totalHeights = new List(); var task = new TaskCompletionSource(); - var renderer = new ScoreRenderer(settings); - renderer.Width = 1300; - + var renderer = new ScoreRenderer(settings) + { + Width = widths.Shift() + }; + renderer.PreRender.On(isResize => + { + results.Add(new List()); + totalWidths.Add(0); + totalHeights.Add(0); + }); renderer.PartialRenderFinished.On(e => { if (e != null) { - result.Add(e); + results[^1].Add(e); } }); renderer.RenderFinished.On(e => { - totalWidth = e.TotalWidth; - totalHeight = e.TotalHeight; - result.Add(e); - task.SetResult(null); + totalWidths[^1] = e.TotalWidth; + totalHeights[^1] = e.TotalHeight; + results[^1].Add(e); + if (widths.Count > 0) + { + renderer.Width = widths.Shift(); + renderer.ResizeRender(); + } + else + { + task.SetResult(null); + } }); renderer.Error.On((e) => { task.SetException(e); }); + renderer.RenderScore(score, tracks); - if (await Task.WhenAny(task.Task, Task.Delay(2000)) == task.Task) + if (await Task.WhenAny(task.Task, Task.Delay(2000 * referenceImages.Count)) == task.Task) { - CompareVisualResult( - totalWidth, - totalHeight, - result, - referenceFileName, - referenceFileData, - message - ); + for (var i = 0; i < results.Count; i++) + { + if (referenceImages[i] != null) + { + CompareVisualResult( + totalWidths[i], + totalHeights[i], + results[i], + referenceImages[i]!, + referenceFileData[i]!, + message, + tolerancePercent + ); + } + } } else { @@ -127,43 +99,71 @@ public static async Task RunVisualTestScore(Score score, string referenceFileNam } } + private static void PrepareSettingsForTest(ref Settings? settings) + { + settings ??= new Settings(); + settings.Core.Engine = "skia"; + settings.Core.EnableLazyLoading = false; + settings.Core.UseWorkers = false; + + settings.Display.Resources.CopyrightFont.Family = "Roboto"; + settings.Display.Resources.TitleFont.Family = "PT Serif"; + settings.Display.Resources.SubTitleFont.Family = "PT Serif"; + settings.Display.Resources.WordsFont.Family = "PT Serif"; + settings.Display.Resources.EffectFont.Family = "PT Serif"; + settings.Display.Resources.FretboardNumberFont.Family = "Roboto"; + settings.Display.Resources.TablatureFont.Family = "Roboto"; + settings.Display.Resources.GraceFont.Family = "Roboto"; + settings.Display.Resources.BarNumberFont.Family = "Roboto"; + settings.Display.Resources.FingeringFont.Family = "PT Serif"; + settings.Display.Resources.MarkerFont.Family = "PT Serif"; + + LoadFonts(); + } + + private static bool _fontsLoaded; + private static void LoadFonts() + { + if (_fontsLoaded) + { + return; + } + + _fontsLoaded = true; + var fonts = new[] + { + "font/roboto/Roboto-Regular.ttf", + "font/roboto/Roboto-Italic.ttf", + "font/roboto/Roboto-Bold.ttf", + "font/roboto/Roboto-BoldItalic.ttf", + "font/ptserif/PTSerif-Regular.ttf", + "font/ptserif/PTSerif-Italic.ttf", + "font/ptserif/PTSerif-Bold.ttf", + "font/ptserif/PTSerif-BoldItalic.ttf" + }; + foreach (var font in fonts) + { + var data = File.ReadAllBytes(font); + SkiaCanvas.RegisterCustomFont(data); + } + } + private static void CompareVisualResult(double totalWidth, double totalHeight, List result, string referenceFileName, - Uint8Array referenceFileData, string? message) + Uint8Array referenceFileData, string? message, double tolerancePercent = 1) { - // TODO: get Skia to render like Chrome - // https://github.com/mono/SkiaSharp/issues/1253 - return; - - // ReSharper disable once HeuristicUnreachableCode -#pragma warning disable 162 SKBitmap finalBitmap; using (var finalImageSurface = SKSurface.Create(new SKImageInfo((int) totalWidth, (int) totalHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul))) { - var point = new SKPoint(); - var rowHeight = 0; foreach (var partialResult in result) { var partialCanvas = partialResult.RenderResult; if (partialCanvas is SKImage img) { - finalImageSurface.Canvas.DrawImage(img, point); - if (partialResult.Height > rowHeight) - { - rowHeight = img.Height; - } - - point.X += img.Width; - - if (point.X >= totalWidth) - { - point.X = 0; - point.Y += rowHeight; - rowHeight = 0; - } + finalImageSurface.Canvas.DrawImage(img, (float)partialResult.X, (float)partialResult.Y); } } @@ -174,12 +174,12 @@ private static void CompareVisualResult(double totalWidth, double totalHeight, var finalImageFileName = Path.ChangeExtension(referenceFileName, ".new.png"); using (finalBitmap) { - var dir = Path.GetDirectoryName(finalImageFileName); + var dir = Path.GetDirectoryName(finalImageFileName)!; Directory.CreateDirectory(dir); using (var fileStream = new SKFileWStream(finalImageFileName)) { - SKPixmap.Encode(fileStream, finalBitmap, SKEncodedImageFormat.Png, 100); + finalBitmap.Encode(fileStream, SKEncodedImageFormat.Png, 100); } SKBitmap referenceBitmap; @@ -190,38 +190,71 @@ private static void CompareVisualResult(double totalWidth, double totalHeight, using (referenceBitmap) { - var compareResult = PixelMatch.Run(finalBitmap, referenceBitmap, - new PixelMatchOptions - { - Threshold = 0.8, - IncludeAntiAlias = false, - IgnoreTransparent = true, - CreateOutputImage = true - }); - - - using (compareResult.Output) + try { - Assert.IsTrue(compareResult.SizesMatch, "Dimensions differ"); - if (compareResult.Mismatch > 0.01) + Assert.AreEqual(totalWidth, referenceBitmap.Width, + "Width of images does not match"); + Assert.AreEqual(totalHeight, referenceBitmap.Height, + "Height of images does not match"); + var diffData = new Uint8Array(finalBitmap.Bytes.Length); + var match = PixelMatch.Match( + new Uint8Array(referenceBitmap.Bytes), + new Uint8Array(finalBitmap.Bytes), + diffData, + referenceBitmap.Width, + referenceBitmap.Height, + new PixelMatchOptions + { + Threshold = 0.3, + IncludeAA = false, + DiffMask = true, + Alpha = 1 + }); + + var totalPixels = match.TotalPixels - match.TransparentPixels; + var percentDifference = (match.DifferentPixels / totalPixels) * 100; + var pass = percentDifference < tolerancePercent; + if (!pass) { + var percentDifferenceText = percentDifference.ToString("0.00"); + var msg = + $"Difference between original and new image is too big: {match.DifferentPixels}/${totalPixels} ({percentDifferenceText}%) ${message}"; + var diffImageName = Path.ChangeExtension(referenceFileName, ".diff.png"); using (var fileStream = new SKFileWStream(diffImageName)) { - SKPixmap.Encode(fileStream, compareResult.Output, + var diff = SKBitmap.FromImage( + SKImage.FromPixels(referenceBitmap.Info, + SKData.Create(new MemoryStream(diffData.Data.Array!))) + ); + diff?.Encode(fileStream, + SKEncodedImageFormat.Png, 100); + } + + var newImageName = + Path.ChangeExtension(referenceFileName, ".new.png"); + using (var fileStream = new SKFileWStream(newImageName)) + { + finalBitmap.Encode(fileStream, SKEncodedImageFormat.Png, 100); } - Assert.Fail( - $"Difference between original and new image is too big: {compareResult.Mismatch:P}, {compareResult.DifferentPixels}/{compareResult.TotalPixels}"); + Assert.Fail(msg); } } + catch (AssertFailedException) + { + throw; + } + catch (Exception e) + { + Assert.Fail($"Error comparing images: {e}, ${message}"); + } } } File.Delete(finalImageFileName); -#pragma warning restore 162 } } } diff --git a/src.csharp/AlphaTab.Windows/AlphaTab.Windows.csproj b/src.csharp/AlphaTab.Windows/AlphaTab.Windows.csproj index 74bad065a..37aa2ee0a 100644 --- a/src.csharp/AlphaTab.Windows/AlphaTab.Windows.csproj +++ b/src.csharp/AlphaTab.Windows/AlphaTab.Windows.csproj @@ -6,7 +6,7 @@ AlphaTab.Windows true true - netcoreapp3.1 + netcoreapp3.1;net6.0-windows true true $(NoWarn);NU5105 @@ -23,7 +23,7 @@ - + diff --git a/src.csharp/AlphaTab.Windows/NAudioSynthOutput.cs b/src.csharp/AlphaTab.Windows/NAudioSynthOutput.cs index 50e646d58..bfa349f37 100644 --- a/src.csharp/AlphaTab.Windows/NAudioSynthOutput.cs +++ b/src.csharp/AlphaTab.Windows/NAudioSynthOutput.cs @@ -13,11 +13,12 @@ namespace AlphaTab public class NAudioSynthOutput : WaveProvider32, ISynthOutput, IDisposable { private const int BufferSize = 4096; - private const int BufferCount = 10; private const int PreferredSampleRate = 44100; - + private DirectSoundOut _context; private CircularSampleBuffer _circularBuffer; + private int _bufferCount = 0; + private int _requestedBufferCount = 0; /// public double SampleRate => PreferredSampleRate; @@ -39,16 +40,26 @@ public void Activate() /// - public void Open() + public void Open(double bufferTimeInMilliseconds) { - _circularBuffer = new CircularSampleBuffer(BufferSize * BufferCount); - + _bufferCount = (int)( + (bufferTimeInMilliseconds * PreferredSampleRate) / + 1000 / + BufferSize + ); + _circularBuffer = new CircularSampleBuffer(BufferSize * _bufferCount); _context = new DirectSoundOut(100); _context.Init(this); ((EventEmitter) Ready).Trigger(); } + /// + public void Destroy() + { + Dispose(); + } + /// public void Dispose() { @@ -82,6 +93,7 @@ public void Pause() public void AddSamples(Float32Array f) { _circularBuffer.Write(f, 0, f.Length); + _requestedBufferCount--; } /// @@ -94,12 +106,19 @@ private void RequestBuffers() { // if we fall under the half of buffers // we request one half - const int count = BufferCount / 2 * BufferSize; - if (_circularBuffer.Count < count && SampleRequest != null) + var halfBufferCount = _bufferCount / 2; + var halfSamples = halfBufferCount * BufferSize; + // Issue #631: it can happen that requestBuffers is called multiple times + // before we already get samples via addSamples, therefore we need to + // remember how many buffers have been requested, and consider them as available. + var bufferedSamples = _circularBuffer.Count + _requestedBufferCount * BufferSize; + + if (bufferedSamples < halfSamples) { - for (var i = 0; i < BufferCount / 2; i++) + for (var i = 0; i < halfBufferCount; i++) { ((EventEmitter) SampleRequest).Trigger(); + _requestedBufferCount++; } } } @@ -108,13 +127,14 @@ private void RequestBuffers() public override int Read(float[] buffer, int offset, int count) { var read = new Float32Array(count); - _circularBuffer.Read(read, 0, System.Math.Min(read.Length, _circularBuffer.Count)); + + var samplesFromBuffer = _circularBuffer.Read(read, 0, System.Math.Min(read.Length, _circularBuffer.Count)); Buffer.BlockCopy(read.Data, 0, buffer, offset * sizeof(float), count * sizeof(float)); var samples = count / 2; - ((EventEmitterOfT) SamplesPlayed).Trigger(samples); + ((EventEmitterOfT) SamplesPlayed).Trigger(samples / SynthConstants.AudioChannels); RequestBuffers(); diff --git a/src.csharp/AlphaTab.Windows/WinForms/AlphaTabControl.cs b/src.csharp/AlphaTab.Windows/WinForms/AlphaTabControl.cs index d98831391..00cedbf61 100644 --- a/src.csharp/AlphaTab.Windows/WinForms/AlphaTabControl.cs +++ b/src.csharp/AlphaTab.Windows/WinForms/AlphaTabControl.cs @@ -143,7 +143,7 @@ protected override void OnControlAdded(ControlEventArgs e) } } - private void OnTracksChanged(object sender, NotifyCollectionChangedEventArgs e) + private void OnTracksChanged(object? sender, NotifyCollectionChangedEventArgs e) { RenderTracks(); } diff --git a/src.csharp/AlphaTab.Windows/WinForms/AlphaTabLayoutPanel.cs b/src.csharp/AlphaTab.Windows/WinForms/AlphaTabLayoutPanel.cs index a017dab5e..faefe961d 100644 --- a/src.csharp/AlphaTab.Windows/WinForms/AlphaTabLayoutPanel.cs +++ b/src.csharp/AlphaTab.Windows/WinForms/AlphaTabLayoutPanel.cs @@ -6,51 +6,10 @@ namespace AlphaTab.WinForms { internal class AlphaTabLayoutPanel : Panel { - private AlphaTabLayoutEngine? _laoyutEngine; - - public override LayoutEngine LayoutEngine => - _laoyutEngine ??= new AlphaTabLayoutEngine(); - public AlphaTabLayoutPanel() { base.DoubleBuffered = true; ResizeRedraw = true; } - - private class AlphaTabLayoutEngine : LayoutEngine - { - public override bool Layout(object container, LayoutEventArgs layoutEventArgs) - { - var parent = (Control) container; - - var xChild = 0; - var yChild = 0; - - var rowHeight = 0; - - foreach (Control? child in parent.Controls) - { - if (child != null) - { - child.Location = new Point(xChild, yChild); - - xChild += child.Width; - if (child.Height > rowHeight) - { - rowHeight = child.Height; - } - - if (xChild >= parent.Width) - { - xChild = 0; - yChild += rowHeight; - rowHeight = 0; - } - } - } - - return false; - } - } } } diff --git a/src.csharp/AlphaTab.Windows/WinForms/ControlContainer.cs b/src.csharp/AlphaTab.Windows/WinForms/ControlContainer.cs index ea7defd03..1b71c0179 100644 --- a/src.csharp/AlphaTab.Windows/WinForms/ControlContainer.cs +++ b/src.csharp/AlphaTab.Windows/WinForms/ControlContainer.cs @@ -1,6 +1,7 @@ using System.Drawing; using System.Windows.Forms; using AlphaTab.Platform; +using AlphaTab.Rendering.Utils; namespace AlphaTab.WinForms { @@ -42,18 +43,6 @@ public ControlContainer(Control control) ); } - public double Top - { - get => Control.Top; - set => Control.Top = (int)value; - } - - public double Left - { - get => Control.Left; - set => Control.Left = (int)value; - } - public double Width { get => Control.ClientSize.Width - Control.Padding.Horizontal; @@ -116,6 +105,14 @@ public void Clear() Control.Controls.Clear(); } + public void SetBounds(double x, double y, double w, double h) + { + Control.Left = (int)x; + Control.Top = (int)y; + Control.Width = (int)w; + Control.Height = (int)h; + } + public IEventEmitter Resize { get; set; } public IEventEmitterOfT MouseDown { get; set; } public IEventEmitterOfT MouseMove { get; set; } diff --git a/src.csharp/AlphaTab.Windows/WinForms/WinFormsUiFacade.cs b/src.csharp/AlphaTab.Windows/WinForms/WinFormsUiFacade.cs index d1745eb52..6359bfe8c 100644 --- a/src.csharp/AlphaTab.Windows/WinForms/WinFormsUiFacade.cs +++ b/src.csharp/AlphaTab.Windows/WinForms/WinFormsUiFacade.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -14,6 +15,10 @@ namespace AlphaTab.WinForms internal class WinFormsUiFacade : ManagedUiFacade { private readonly AlphaTabLayoutPanel _layoutPanel; + + private readonly Dictionary _resultIdToElementLookup = + new Dictionary(); + private event Action? InternalRootContainerBecameVisible; public override IContainer RootContainer { get; } @@ -67,7 +72,7 @@ void OnVisibilityChanged(object? sender, EventArgs e) protected override Stream? OpenDefaultSoundFont() { return typeof(NAudioSynthOutput).Assembly.GetManifestResourceStream( - typeof(NAudioSynthOutput), "default.sf2"); + typeof(NAudioSynthOutput), "default.sf2"); } public override void Initialize(AlphaTabApiBase api, @@ -76,6 +81,7 @@ public override void Initialize(AlphaTabApiBase api, base.Initialize(api, control); api.Settings = control.Settings; control.SettingsChanged += OnSettingsChanged; + api.SettingsUpdated.On(OnSettingsUpdated); } private void OnSettingsChanged(Settings s) @@ -99,6 +105,7 @@ public override void Destroy() { SettingsContainer.SettingsChanged -= OnSettingsChanged; _layoutPanel.Controls.Clear(); + Api.SettingsUpdated.Off(OnSettingsUpdated); } public override IContainer CreateCanvasElement() @@ -106,14 +113,57 @@ public override IContainer CreateCanvasElement() return new ControlContainer(_layoutPanel); } + public override void InitialRender() + { + Api.Renderer.PreRender.On(_ => { _resultIdToElementLookup.Clear(); }); + base.InitialRender(); + } + public override void TriggerEvent(IContainer container, string eventName, object? details = null, IMouseEventArgs? originalEvent = null) { } + public override void BeginUpdateRenderResults(RenderFinishedEventArgs? r) + { + SettingsContainer.BeginInvoke((Action)(renderResult => + { + + if (renderResult == null || + !_resultIdToElementLookup.TryGetValue(renderResult.Id, out var placeholder)) + { + return; + } + + var body = renderResult.RenderResult; + + Bitmap? source = null; + switch (body) + { + case string _: + // TODO: svg support + return; + case SKImage skiaImage: + using (skiaImage) + { + source = SkiaUtil.ToBitmap(skiaImage); + } + + break; + case Bitmap image: + source = image; + break; + } + + var oldImage = placeholder.Image; + placeholder.Image = source; + oldImage?.Dispose(); + }), r); + } + public override void BeginAppendRenderResults(RenderFinishedEventArgs? r) { - SettingsContainer.BeginInvoke((Action) (renderResult => + SettingsContainer.BeginInvoke((Action)(renderResult => { var panel = _layoutPanel; @@ -134,63 +184,48 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs? r) // NOTE: here we try to replace existing children else { - var body = renderResult.RenderResult; - - Bitmap? source = null; - if (body is string) + if (TotalResultCount.TryPeek(out var counter)) { - // TODO: svg support - return; - } - - if (body is SKImage skiaImage) - { - using (skiaImage) + PictureBox placeholder; + if (counter.Count < panel.Controls.Count) { - source = SkiaUtil.ToBitmap(skiaImage); + placeholder = (PictureBox)panel.Controls[counter.Count]; } - } - else if (body is Bitmap image) - { - source = image; - } - - if (source != null) - { - if (TotalResultCount.TryPeek(out var counter)) + else { - if (counter.Count < panel.Controls.Count) - { - var img = (PictureBox) panel.Controls[counter.Count]; - img.Width = (int) renderResult.Width; - img.Height = (int) renderResult.Height; - var oldImg = img.Image; - img.Image = source; - oldImg?.Dispose(); - } - else + placeholder = new PictureBox { - var img = new PictureBox - { - AutoSize = false, - BackColor = _layoutPanel.ForeColor, - Width = (int) renderResult.Width, - Height = (int) renderResult.Height, - Image = source, - Padding = Padding.Empty, - Margin = Padding.Empty, - BorderStyle = BorderStyle.None - }; - panel.Controls.Add(img); - } - - counter.Count++; + AutoSize = false, + BackColor = _layoutPanel.ForeColor, + Padding = Padding.Empty, + Margin = Padding.Empty, + BorderStyle = BorderStyle.None + }; + panel.Controls.Add(placeholder); } + + placeholder.Left = (int)renderResult.X; + placeholder.Top = (int)renderResult.Y; + placeholder.Width = (int)renderResult.Width; + placeholder.Height = (int)renderResult.Height; + + _resultIdToElementLookup[renderResult.Id] = placeholder; + Api.Renderer.RenderResult(renderResult.Id); + + counter.Count++; } } }), r); } + private void OnSettingsUpdated() + { + foreach (Control control in _layoutPanel.Controls) + { + control.BackColor = _layoutPanel.ForeColor; + } + } + public override void DestroyCursors() { @@ -212,7 +247,7 @@ public override void RemoveHighlights() { } - public override void HighlightElements(string groupId) + public override void HighlightElements(string groupId, double masterBarIndex) { } @@ -228,7 +263,7 @@ public override IContainer GetScrollContainer() public override Bounds GetOffset(IContainer? relativeTo, IContainer container) { - var containerWinForms = ((ControlContainer) container).Control; + var containerWinForms = ((ControlContainer)container).Control; var left = 0; var top = 0; @@ -252,14 +287,14 @@ public override Bounds GetOffset(IContainer? relativeTo, IContainer container) public override void ScrollToY(IContainer scrollElement, double offset, double speed) { - var c = ((ControlContainer) scrollElement).Control; - c.AutoScrollOffset = new Point(c.AutoScrollOffset.X, (int) offset); + var c = ((ControlContainer)scrollElement).Control; + c.AutoScrollOffset = new Point(c.AutoScrollOffset.X, (int)offset); } public override void ScrollToX(IContainer scrollElement, double offset, double speed) { - var c = ((ControlContainer) scrollElement).Control; - c.AutoScrollOffset = new Point((int) offset, c.AutoScrollOffset.Y); + var c = ((ControlContainer)scrollElement).Control; + c.AutoScrollOffset = new Point((int)offset, c.AutoScrollOffset.Y); } } } diff --git a/src.csharp/AlphaTab.Windows/Wpf/AlphaTab.cs b/src.csharp/AlphaTab.Windows/Wpf/AlphaTab.cs index 527efbacb..c947e662a 100644 --- a/src.csharp/AlphaTab.Windows/Wpf/AlphaTab.cs +++ b/src.csharp/AlphaTab.Windows/Wpf/AlphaTab.cs @@ -60,7 +60,7 @@ private void UnregisterObservableCollection(INotifyCollectionChanged collection) collection.CollectionChanged -= OnTracksChanged; } - private void OnTracksChanged(object sender, NotifyCollectionChangedEventArgs e) + private void OnTracksChanged(object? sender, NotifyCollectionChangedEventArgs e) { RenderTracks(); } diff --git a/src.csharp/AlphaTab.Windows/Wpf/AlphaTabLayoutPanel.cs b/src.csharp/AlphaTab.Windows/Wpf/AlphaTabLayoutPanel.cs deleted file mode 100644 index abf06c5f0..000000000 --- a/src.csharp/AlphaTab.Windows/Wpf/AlphaTabLayoutPanel.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace AlphaTab.Wpf -{ - internal class AlphaTabLayoutPanel : Panel - { - protected override Size MeasureOverride(Size availableSize) - { - foreach (UIElement? child in InternalChildren) - { - child?.Measure(availableSize); - } - return new Size - { - Width = double.IsInfinity(availableSize.Width) ? MinWidth : availableSize.Width, - Height = double.IsInfinity(availableSize.Height) ? MinHeight : availableSize.Height - }; - } - - protected override Size ArrangeOverride(Size finalSize) - { - var xChild = 0.0; - var yChild = 0.0; - - var rowHeight = 0.0; - - foreach (UIElement? child in InternalChildren) - { - if (child != null) - { - child.Arrange(new Rect(xChild, yChild, child.DesiredSize.Width, - child.DesiredSize.Height)); - - xChild += child.DesiredSize.Width; - if (child.DesiredSize.Height > rowHeight) - { - rowHeight = child.DesiredSize.Height; - } - - if (xChild >= finalSize.Width) - { - xChild = 0; - yChild += rowHeight; - rowHeight = 0; - } - } - } - - return finalSize; - } - } -} diff --git a/src.csharp/AlphaTab.Windows/Wpf/FrameworkElementContainer.cs b/src.csharp/AlphaTab.Windows/Wpf/FrameworkElementContainer.cs index cec8eb998..701c7217c 100644 --- a/src.csharp/AlphaTab.Windows/Wpf/FrameworkElementContainer.cs +++ b/src.csharp/AlphaTab.Windows/Wpf/FrameworkElementContainer.cs @@ -3,6 +3,7 @@ using System.Windows.Controls; using System.Windows.Media.Animation; using AlphaTab.Platform; +using AlphaTab.Rendering.Utils; namespace AlphaTab.Wpf { @@ -44,18 +45,6 @@ public FrameworkElementContainer(FrameworkElement control) ); } - public double Top - { - get => (float) Canvas.GetTop(Control); - set => Canvas.SetTop(Control, value); - } - - public double Left - { - get => (float) Canvas.GetLeft(Control); - set => Canvas.SetLeft(Control, value); - } - public double Width { get => (float) Control.ActualWidth; @@ -133,7 +122,6 @@ public void TransitionToX(double duration, double x) new DoubleAnimation(x, new Duration(TimeSpan.FromMilliseconds(duration)))); } - public void Clear() { if (Control is Panel p) @@ -142,6 +130,14 @@ public void Clear() } } + public void SetBounds(double x, double y, double w, double h) + { + Canvas.SetLeft(Control, x); + Canvas.SetTop(Control, y); + Control.Width = w; + Control.Height = h; + } + public IEventEmitter Resize { get; set; } public IEventEmitterOfT MouseDown { get; set; } public IEventEmitterOfT MouseMove { get; set; } diff --git a/src.csharp/AlphaTab.Windows/Wpf/GdiImageSource.cs b/src.csharp/AlphaTab.Windows/Wpf/GdiImageSource.cs index 85cdd2e8c..cfc5d1f38 100644 --- a/src.csharp/AlphaTab.Windows/Wpf/GdiImageSource.cs +++ b/src.csharp/AlphaTab.Windows/Wpf/GdiImageSource.cs @@ -9,7 +9,8 @@ internal static class GdiImageSource { public static BitmapSource Create(Bitmap image) { - var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, + var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, image.PixelFormat); var bitmapSource = BitmapSource.Create( @@ -17,7 +18,7 @@ public static BitmapSource Create(Bitmap image) bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride); image.UnlockBits(bitmapData); - + bitmapSource.Freeze(); return bitmapSource; } } diff --git a/src.csharp/AlphaTab.Windows/Wpf/SkImageSource.cs b/src.csharp/AlphaTab.Windows/Wpf/SkImageSource.cs index d6a8a827b..dc8540c7c 100644 --- a/src.csharp/AlphaTab.Windows/Wpf/SkImageSource.cs +++ b/src.csharp/AlphaTab.Windows/Wpf/SkImageSource.cs @@ -20,6 +20,7 @@ public static BitmapSource Create(object data) } bitmap.AddDirtyRect(new Int32Rect(0, 0, info.Width, info.Height)); bitmap.Unlock(); + bitmap.Freeze(); return bitmap; } } diff --git a/src.csharp/AlphaTab.Windows/Wpf/WpfUiFacade.cs b/src.csharp/AlphaTab.Windows/Wpf/WpfUiFacade.cs index b7d020f99..5c15f7c07 100644 --- a/src.csharp/AlphaTab.Windows/Wpf/WpfUiFacade.cs +++ b/src.csharp/AlphaTab.Windows/Wpf/WpfUiFacade.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; +using System.Windows.Data; using System.Windows.Media; +using System.Windows.Shapes; using AlphaTab.Synth; using AlphaTab.Platform; using AlphaTab.Platform.CSharp; @@ -18,6 +21,10 @@ namespace AlphaTab.Wpf internal class WpfUiFacade : ManagedUiFacade { private readonly ScrollViewer _scrollViewer; + + private readonly Dictionary _resultIdToElementLookup = + new Dictionary(); + private event Action? InternalRootContainerBecameVisible; public override IContainer RootContainer { get; } @@ -78,12 +85,14 @@ void OnVisibilityChanged(object sender, public override void Initialize(AlphaTabApiBase api, AlphaTab control) { base.Initialize(api, control); + control.Settings.Core.EnableLazyLoading = false; api.Settings = control.Settings; control.SettingsChanged += OnSettingsChanged; } private void OnSettingsChanged(Settings s) { + s.Core.EnableLazyLoading = false; Api.Settings = s; Api.UpdateSettings(); Api.Render(); @@ -107,25 +116,69 @@ public override void Destroy() public override IContainer CreateCanvasElement() { - var canvas = new WrapPanel + var canvas = new Canvas { - VerticalAlignment = VerticalAlignment.Top, - Orientation = Orientation.Horizontal + VerticalAlignment = VerticalAlignment.Top }; return new FrameworkElementContainer(canvas); } + public override void InitialRender() + { + Api.Renderer.PreRender.On(_ => { _resultIdToElementLookup.Clear(); }); + base.InitialRender(); + } + public override void TriggerEvent(IContainer container, string eventName, object? details = null, IMouseEventArgs? originalEvent = null) { } + public override void BeginUpdateRenderResults(RenderFinishedEventArgs? r) + { + SettingsContainer.Dispatcher?.BeginInvoke( + (Action)(renderResult => + { + if (renderResult == null || + !_resultIdToElementLookup.TryGetValue(renderResult.Id, out var placeholder)) + { + return; + } + + var body = renderResult.RenderResult; + + ImageSource? source = null; + if (body is string) + { + // TODO: svg support + return; + } + + if (body is SKImage skiaImage) + { + using (skiaImage) + { + source = SkImageSource.Create(skiaImage); + } + } + else if (body is System.Drawing.Bitmap image) + { + using (image) + { + source = GdiImageSource.Create(image); + } + } + + placeholder.Source = source; + }), r); + } + public override void BeginAppendRenderResults(RenderFinishedEventArgs? r) { SettingsContainer.Dispatcher?.BeginInvoke( - (Action) (renderResult => + (Action)(renderResult => { - var panel = (WrapPanel) ((FrameworkElementContainer) Api.CanvasElement).Control; + var panel = (Panel)((FrameworkElementContainer)Api.CanvasElement).Control; // null result indicates that the rendering finished if (renderResult == null) @@ -142,56 +195,30 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs? r) // NOTE: here we try to replace existing children else { - var body = renderResult.RenderResult; - - ImageSource? source = null; - if (body is string) - { - // TODO: svg support - return; - } - - if (body is SKImage skiaImage) - { - using (skiaImage) - { - source = SkImageSource.Create(skiaImage); - } - } - else if (body is System.Drawing.Bitmap image) + if (TotalResultCount.TryPeek(out var counter)) { - using (image) + Image placeholder; + if (counter.Count < panel.Children.Count) { - source = GdiImageSource.Create(image); + placeholder = (Image)panel.Children[counter.Count]; } - } - - if (source != null) - { - if (TotalResultCount.TryPeek(out var counter)) + else { - if (counter.Count < panel.Children.Count) - { - var img = (Image) panel.Children[counter.Count]; - img.Width = renderResult.Width; - img.Height = renderResult.Height; - img.Stretch = Stretch.None; - img.SnapsToDevicePixels = true; - img.Source = source; - } - else + placeholder = new Image { - var img = new Image - { - Width = renderResult.Width, - Height = renderResult.Height, - Source = source - }; - panel.Children.Add(img); - } - - counter.Count++; + Stretch = Stretch.None, + SnapsToDevicePixels = true + }; + panel.Children.Add(placeholder); } + + Canvas.SetLeft(placeholder, renderResult.X); + Canvas.SetTop(placeholder, renderResult.Y); + placeholder.Width = renderResult.Width; + placeholder.Height = renderResult.Height; + _resultIdToElementLookup[renderResult.Id] = placeholder; + + counter.Count++; } } }), @@ -200,7 +227,7 @@ public override void BeginAppendRenderResults(RenderFinishedEventArgs? r) public override void DestroyCursors() { - var element = (Panel) ((FrameworkElementContainer) Api.CanvasElement).Control.Parent; + var element = (Panel)((FrameworkElementContainer)Api.CanvasElement).Control.Parent; var cursors = element.Children.OfType() .FirstOrDefault(c => "at-cursors".Equals(c.Tag)); if (cursors != null) @@ -220,25 +247,32 @@ public override Cursors CreateCursors() var selectionWrapper = new Canvas(); - var barCursor = new System.Windows.Shapes.Rectangle + var barCursor = new Rectangle { - Fill = SettingsContainer.BarCursorFill, IsHitTestVisible = false }; - var beatCursor = new System.Windows.Shapes.Rectangle + barCursor.SetBinding(Shape.FillProperty, new Binding(nameof(SettingsContainer.BarCursorFill)) + { + Source = SettingsContainer + }); + + var beatCursor = new Rectangle { - Fill = SettingsContainer.BeatCursorFill, IsHitTestVisible = false, Width = 3 }; + beatCursor.SetBinding(Shape.FillProperty, new Binding(nameof(SettingsContainer.BeatCursorFill)) + { + Source = SettingsContainer + }); cursorWrapper.Children.Add(selectionWrapper); cursorWrapper.Children.Add(barCursor); cursorWrapper.Children.Add(beatCursor); // add cursors to UI - var element = (Panel) ((FrameworkElementContainer) Api.CanvasElement).Control.Parent; + var element = (Panel)((FrameworkElementContainer)Api.CanvasElement).Control.Parent; element.Children.Insert(0, cursorWrapper); return new Cursors( @@ -258,17 +292,22 @@ public override void RemoveHighlights() { } - public override void HighlightElements(string groupId) + public override void HighlightElements(string groupId, double masterBarIndex) { } public override IContainer CreateSelectionElement() { - var selection = new System.Windows.Shapes.Rectangle + var selection = new Rectangle { Fill = SettingsContainer.SelectionFill, IsHitTestVisible = false }; + selection.SetBinding(Shape.FillProperty, + new Binding(nameof(SettingsContainer.SelectionFill)) + { + Source = SettingsContainer + }); return new FrameworkElementContainer(selection); } @@ -279,13 +318,13 @@ public override IContainer GetScrollContainer() public override Bounds GetOffset(IContainer? relativeTo, IContainer container) { - var containerWpf = ((FrameworkElementContainer) container).Control; + var containerWpf = ((FrameworkElementContainer)container).Control; - var canvas = ((FrameworkElementContainer) Api.CanvasElement).Control; + var canvas = ((FrameworkElementContainer)Api.CanvasElement).Control; var position = containerWpf.TranslatePoint(new Point(0, 0), canvas); if (relativeTo != null && - ((FrameworkElementContainer) relativeTo).Control is ScrollViewer sv) + ((FrameworkElementContainer)relativeTo).Control is ScrollViewer sv) { position.Y -= sv.VerticalOffset; position.X -= sv.HorizontalOffset; @@ -293,16 +332,16 @@ public override Bounds GetOffset(IContainer? relativeTo, IContainer container) return new Bounds { - X = (float) position.X, - Y = (float) position.Y, - W = (float) containerWpf.ActualWidth, - H = (float) containerWpf.ActualHeight + X = (float)position.X, + Y = (float)position.Y, + W = (float)containerWpf.ActualWidth, + H = (float)containerWpf.ActualHeight }; } public override void ScrollToY(IContainer scrollElement, double offset, double speed) { - if (((FrameworkElementContainer) scrollElement).Control is ScrollViewer s) + if (((FrameworkElementContainer)scrollElement).Control is ScrollViewer s) { s.ScrollToVerticalOffset(offset); } @@ -313,7 +352,7 @@ public override void ScrollToY(IContainer scrollElement, double offset, double s public override void ScrollToX(IContainer scrollElement, double offset, double speed) { - if (((FrameworkElementContainer) scrollElement).Control is ScrollViewer s) + if (((FrameworkElementContainer)scrollElement).Control is ScrollViewer s) { s.ScrollToHorizontalOffset(offset); } diff --git a/src.csharp/AlphaTab.sln b/src.csharp/AlphaTab.sln index 3ff5fb962..fc36f0207 100644 --- a/src.csharp/AlphaTab.sln +++ b/src.csharp/AlphaTab.sln @@ -9,18 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AlphaTab.Test", "AlphaTab.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Windows", "AlphaTab.Windows\AlphaTab.Windows.csproj", "{FAF5C549-DDAA-4254-B9E4-BB487C433626}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Samples.Player", "Samples\AlphaTab.Samples.Player\AlphaTab.Samples.Player.csproj", "{30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Samples.PngDump", "Samples\AlphaTab.Samples.PngDump\AlphaTab.Samples.PngDump.csproj", "{461D19B0-AD20-4427-8569-FAF78311DA26}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Samples.ScoreDump", "Samples\AlphaTab.Samples.ScoreDump\AlphaTab.Samples.ScoreDump.csproj", "{6A365654-90EE-4726-BD99-4CA5358AB258}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Samples.WinForms", "Samples\AlphaTab.Samples.WinForms\AlphaTab.Samples.WinForms.csproj", "{479765C9-F70E-45EE-984D-A97A33758F32}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlphaTab.Samples.Wpf", "Samples\AlphaTab.Samples.Wpf\AlphaTab.Samples.Wpf.csproj", "{48677CA2-2131-4F70-9D56-E7A272DE26B8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,26 +27,6 @@ Global {FAF5C549-DDAA-4254-B9E4-BB487C433626}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAF5C549-DDAA-4254-B9E4-BB487C433626}.Release|Any CPU.ActiveCfg = Release|Any CPU {FAF5C549-DDAA-4254-B9E4-BB487C433626}.Release|Any CPU.Build.0 = Release|Any CPU - {30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8}.Release|Any CPU.Build.0 = Release|Any CPU - {461D19B0-AD20-4427-8569-FAF78311DA26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {461D19B0-AD20-4427-8569-FAF78311DA26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {461D19B0-AD20-4427-8569-FAF78311DA26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {461D19B0-AD20-4427-8569-FAF78311DA26}.Release|Any CPU.Build.0 = Release|Any CPU - {6A365654-90EE-4726-BD99-4CA5358AB258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6A365654-90EE-4726-BD99-4CA5358AB258}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6A365654-90EE-4726-BD99-4CA5358AB258}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6A365654-90EE-4726-BD99-4CA5358AB258}.Release|Any CPU.Build.0 = Release|Any CPU - {479765C9-F70E-45EE-984D-A97A33758F32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {479765C9-F70E-45EE-984D-A97A33758F32}.Debug|Any CPU.Build.0 = Debug|Any CPU - {479765C9-F70E-45EE-984D-A97A33758F32}.Release|Any CPU.ActiveCfg = Release|Any CPU - {479765C9-F70E-45EE-984D-A97A33758F32}.Release|Any CPU.Build.0 = Release|Any CPU - {48677CA2-2131-4F70-9D56-E7A272DE26B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48677CA2-2131-4F70-9D56-E7A272DE26B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48677CA2-2131-4F70-9D56-E7A272DE26B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48677CA2-2131-4F70-9D56-E7A272DE26B8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,10 +35,5 @@ Global SolutionGuid = {CDCE91E9-ED42-4D67-8B9D-13E73BBA1225} EndGlobalSection GlobalSection(NestedProjects) = preSolution - {30B7CFE6-FC7B-40F7-9D3C-BC27DE4911E8} = {6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77} - {461D19B0-AD20-4427-8569-FAF78311DA26} = {6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77} - {6A365654-90EE-4726-BD99-4CA5358AB258} = {6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77} - {479765C9-F70E-45EE-984D-A97A33758F32} = {6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77} - {48677CA2-2131-4F70-9D56-E7A272DE26B8} = {6ED0C3C1-5142-4D44-AB33-0D9DAFDCEE77} EndGlobalSection EndGlobal diff --git a/src.csharp/AlphaTab/AlphaTab.csproj b/src.csharp/AlphaTab/AlphaTab.csproj index 3bc5d3485..6b2812d85 100644 --- a/src.csharp/AlphaTab/AlphaTab.csproj +++ b/src.csharp/AlphaTab/AlphaTab.csproj @@ -8,7 +8,7 @@ true $(NoWarn);0162;1591;1573;NU5105;0168 $(NoWarn);8600;8601;8602;8603;8604;8605 - netstandard20 + netstandard2.0 enable 8 @@ -25,7 +25,8 @@ - - + + + diff --git a/src.csharp/AlphaTab/Core/EcmaScript/DataView.cs b/src.csharp/AlphaTab/Core/EcmaScript/DataView.cs index 2cc87959c..a437635f7 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/DataView.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/DataView.cs @@ -4,11 +4,16 @@ namespace AlphaTab.Core.EcmaScript { public class DataView { - private readonly ArrayBuffer _buffer; + public ArrayBuffer Buffer { get; } public DataView(ArrayBuffer buffer) { - _buffer = buffer; + Buffer = buffer; + } + + public double GetUint8(double offset) + { + return Buffer.Raw.Array![Buffer.Raw.Offset + (int) offset]; } public void SetUint16(double offset, double value, bool littleEndian) @@ -19,14 +24,14 @@ public void SetUint16(double offset, double value, bool littleEndian) System.Array.Reverse(bytes); } - Buffer.BlockCopy(bytes, 0, _buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, + System.Buffer.BlockCopy(bytes, 0, Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes.Length); } public double GetInt16(double offset, bool littleEndian) { var bytes = new byte[sizeof(short)]; - Buffer.BlockCopy(_buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, bytes, 0, + System.Buffer.BlockCopy(Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes, 0, bytes.Length); if (littleEndian != BitConverter.IsLittleEndian) { @@ -44,14 +49,14 @@ public void SetInt16(double offset, double value, bool littleEndian) System.Array.Reverse(bytes); } - Buffer.BlockCopy(bytes, 0, _buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, + System.Buffer.BlockCopy(bytes, 0, Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes.Length); } public double GetUint32(double offset, bool littleEndian) { var bytes = new byte[sizeof(uint)]; - Buffer.BlockCopy(_buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, bytes, 0, + System.Buffer.BlockCopy(Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes, 0, bytes.Length); if (littleEndian != BitConverter.IsLittleEndian) { @@ -61,6 +66,19 @@ public double GetUint32(double offset, bool littleEndian) return BitConverter.ToUInt32(bytes, 0); } + public double GetInt32(double offset, bool littleEndian) + { + var bytes = new byte[sizeof(uint)]; + System.Buffer.BlockCopy(Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes, 0, + bytes.Length); + if (littleEndian != BitConverter.IsLittleEndian) + { + System.Array.Reverse(bytes); + } + + return BitConverter.ToInt32(bytes, 0); + } + public void SetInt32(double offset, double value, bool littleEndian) { var bytes = BitConverter.GetBytes((int) value); @@ -69,14 +87,14 @@ public void SetInt32(double offset, double value, bool littleEndian) System.Array.Reverse(bytes); } - Buffer.BlockCopy(bytes, 0, _buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, bytes + System.Buffer.BlockCopy(bytes, 0, Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes .Length); } public double GetUint16(double offset, bool littleEndian) { var bytes = new byte[sizeof(ushort)]; - Buffer.BlockCopy(_buffer.Raw.Array, _buffer.Raw.Offset + (int) offset, bytes, 0, + System.Buffer.BlockCopy(Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes, 0, bytes.Length); if (littleEndian != BitConverter.IsLittleEndian) { @@ -88,12 +106,25 @@ public double GetUint16(double offset, bool littleEndian) public void SetUint8(double offset, double value) { - _buffer.Raw.Array[_buffer.Raw.Offset + (int) offset] = (byte) value; + Buffer.Raw.Array![Buffer.Raw.Offset + (int) offset] = (byte) value; } public double GetInt8(double offset) { - return (sbyte) _buffer.Raw.Array[_buffer.Raw.Offset + (int) offset]; + return (sbyte) Buffer.Raw.Array![Buffer.Raw.Offset + (int) offset]; + } + + public double SetUint32(double offset, double value, bool littleEndian) + { + var bytes = BitConverter.GetBytes((uint)value); + if (littleEndian != BitConverter.IsLittleEndian) + { + System.Array.Reverse(bytes); + } + + System.Buffer.BlockCopy(bytes, 0, Buffer.Raw.Array!, Buffer.Raw.Offset + (int) offset, bytes + .Length); + return value; } } } diff --git a/src.csharp/AlphaTab/Core/EcmaScript/Map.cs b/src.csharp/AlphaTab/Core/EcmaScript/Map.cs index fe404c4ec..87ec8d25d 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/Map.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/Map.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -158,4 +158,4 @@ public IEnumerable Values() return _data.Values; } } -} +} \ No newline at end of file diff --git a/src.csharp/AlphaTab/Core/EcmaScript/MapEntry.cs b/src.csharp/AlphaTab/Core/EcmaScript/MapEntry.cs index b8fdb0719..7aff065e4 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/MapEntry.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/MapEntry.cs @@ -1,4 +1,4 @@ -namespace AlphaTab.Core.EcmaScript +namespace AlphaTab.Core.EcmaScript { public class MapEntry { @@ -17,4 +17,4 @@ public void Deconstruct(out TKey key, out TValue value) value = Value; } } -} +} \ No newline at end of file diff --git a/src.csharp/AlphaTab/Core/EcmaScript/Math.cs b/src.csharp/AlphaTab/Core/EcmaScript/Math.cs index c0961ee27..40734bc98 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/Math.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/Math.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace AlphaTab.Core.EcmaScript { @@ -17,6 +18,16 @@ public static double Abs(double v) return System.Math.Abs(v); } + public static double Max(params double[] items) + { + return items.Max(); + } + + public static double Min(params double[] items) + { + return items.Min(); + } + public static double Max(double a, double b) { return System.Math.Max(a, b); diff --git a/src.csharp/AlphaTab/Core/EcmaScript/Set.cs b/src.csharp/AlphaTab/Core/EcmaScript/Set.cs index 09af796b8..fa03971be 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/Set.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/Set.cs @@ -49,5 +49,10 @@ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + + public void Delete(T item) + { + _data.Remove(item); + } } } diff --git a/src.csharp/AlphaTab/Core/EcmaScript/Uint32Array.cs b/src.csharp/AlphaTab/Core/EcmaScript/Uint32Array.cs index c04fbe6e5..3bf82c14b 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/Uint32Array.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/Uint32Array.cs @@ -1,5 +1,7 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; namespace AlphaTab.Core.EcmaScript @@ -25,7 +27,7 @@ public double this[double index] public IEnumerator GetEnumerator() { - return ((IEnumerable)_data).GetEnumerator(); + return ((IEnumerable) _data).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() diff --git a/src.csharp/AlphaTab/Core/EcmaScript/Uint8Array.cs b/src.csharp/AlphaTab/Core/EcmaScript/Uint8Array.cs index f0ce5bc7d..2745242e7 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/Uint8Array.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/Uint8Array.cs @@ -11,6 +11,7 @@ public class Uint8Array : IEnumerable, IEnumerable private ArraySegment _data; public double Length => _data.Count; + public double ByteOffset => _data.Offset; public ArrayBuffer Buffer => new ArrayBuffer(_data); diff --git a/src.csharp/AlphaTab/Core/EcmaScript/ValueTypeMap.cs b/src.csharp/AlphaTab/Core/EcmaScript/ValueTypeMap.cs index 1f7a8f0b3..e68a2a9fa 100644 --- a/src.csharp/AlphaTab/Core/EcmaScript/ValueTypeMap.cs +++ b/src.csharp/AlphaTab/Core/EcmaScript/ValueTypeMap.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -70,4 +70,4 @@ public void ForEach(Action callback) } } } -} +} \ No newline at end of file diff --git a/src.csharp/AlphaTab/Core/Globals.cs b/src.csharp/AlphaTab/Core/Globals.cs index 5cec54034..efbca4e0a 100644 --- a/src.csharp/AlphaTab/Core/Globals.cs +++ b/src.csharp/AlphaTab/Core/Globals.cs @@ -7,6 +7,11 @@ public static class Globals public const double NaN = double.NaN; public static Console Console { get; } = new Console(); + public static double ParseInt(char c) + { + return ParseInt(c.ToString()); + } + public static double ParseInt(string s) { if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var d)) @@ -17,6 +22,11 @@ public static double ParseInt(string s) return double.NaN; } + public static double ParseInt(char c, int radix) + { + return ParseInt(c.ToString(), radix); + } + public static double ParseInt(string s, int radix) { if (radix == 16 && int.TryParse(s, NumberStyles.HexNumber, diff --git a/src.csharp/AlphaTab/Core/TypeHelper.cs b/src.csharp/AlphaTab/Core/TypeHelper.cs index 483199156..46223a119 100644 --- a/src.csharp/AlphaTab/Core/TypeHelper.cs +++ b/src.csharp/AlphaTab/Core/TypeHelper.cs @@ -14,6 +14,21 @@ public static IList CreateList(params T[] values) return new List(values); } + public static void Add(this IList list, IList newItems) + { + if(list is List l) + { + l.AddRange(newItems); + } + else + { + foreach (var i in newItems) + { + list.Add(i); + } + } + } + public static IList Splice(this IList data, double start, double deleteCount) { var items = data.GetRange((int) start, (int) deleteCount); @@ -33,7 +48,7 @@ public static IList Splice(this IList data, double start, double delete public static IList Slice(this IList data) { - return new List(new System.Collections.Generic.List(data)); + return new List(data); } public static void Reverse(this IList data) @@ -101,6 +116,13 @@ public static void Unshift(this IList data, T item) data.Insert(0, item); } + public static T Shift(this IList data) + { + var i = data[0]; + data.RemoveAt(0); + return i; + } + public static T Pop(this IList data) { if (data.Count > 0) @@ -128,7 +150,7 @@ public static IList Fill(this IList data, T i) public static void InsertRange(this IList data, int index, IEnumerable newItems) { - if (data is System.Collections.Generic.List l) + if (data is List l) { l.InsertRange(index, newItems); } @@ -142,11 +164,11 @@ public static void InsertRange(this IList data, int index, IEnumerable } } - public static void Sort(this IList data, Func func) + public static IList Sort(this IList data, Func func) { switch (data) { - case System.Collections.Generic.List l: + case List l: l.Sort((a, b) => (int) func(a, b)); break; case T[] array: @@ -156,6 +178,8 @@ public static void Sort(this IList data, Func func) throw new NotSupportedException("Cannot sort list of type " + data.GetType().FullName); } + + return data; } public static void Sort(this IList data) { @@ -186,9 +210,15 @@ public static IList Map(this IEnumerable sourc } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEnumerable Reversed(this IEnumerable source) + public static IList Reversed(this IList source) { - return source.Reverse(); + if (source is List list) + { + list.Reverse(); + return list; + } + + throw new ArgumentException("Unsupported type for in-place reversing"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -260,7 +290,7 @@ public static MapEntry CreateMapEntry(TKey key, TVal return new MapEntry(key, value); } - public static string ToString(this double num, int radix) + public static string ToInvariantString(this double num, int radix) { if (radix == 16) { @@ -270,6 +300,21 @@ public static string ToString(this double num, int radix) return num.ToString(CultureInfo.InvariantCulture); } + public static string ToInvariantString(this double num) + { + return num.ToString(CultureInfo.InvariantCulture); + } + + public static string ToInvariantString(this int num) + { + return num.ToString(CultureInfo.InvariantCulture); + } + + public static string ToInvariantString(this Enum num) + { + return ((IConvertible)num).ToInt32(CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RegExp CreateRegex(string pattern, string flags) { @@ -293,6 +338,11 @@ public static bool IsTruthy(object? s) { return s != null; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTruthy(bool? b) + { + return b.GetValueOrDefault(); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsTruthy(double s) @@ -308,11 +358,30 @@ public static IList Map(this IList source, } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string Substring(this string s, double startIndex, double endIndex) + public static IList Map(this IList source, + Func func) + { + return source.Select(i => (double)func(i)).ToList(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SubstringIndex(this string s, double startIndex) + { + return s.Substring((int) startIndex); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SubstringIndex(this string s, double startIndex, double endIndex) { return s.Substring((int) startIndex, (int) (endIndex - startIndex)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ReplaceAll(this string s, string before, string after) + { + return s.Replace(before, after); + } + public static string TypeOf(object? actual) { switch (actual) @@ -339,5 +408,17 @@ public static string TypeOf(object? actual) return "object"; } } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable SetInitializer(params T[] items) + { + return items; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable MapInitializer(params T[] items) + { + return items; + } } } diff --git a/src.csharp/AlphaTab/Environment.cs b/src.csharp/AlphaTab/Environment.cs index bf8454f65..f083ed381 100644 --- a/src.csharp/AlphaTab/Environment.cs +++ b/src.csharp/AlphaTab/Environment.cs @@ -1,4 +1,3 @@ - using System; using System.Threading; using System.Threading.Tasks; @@ -12,10 +11,8 @@ partial class Environment public const bool SupportsTextDecoder = true; public static void PlatformInit() { - } - public static Action Throttle(Action action, double delay) { CancellationTokenSource? cancellationTokenSource = null; @@ -37,15 +34,11 @@ private static void CreatePlatformSpecificRenderEngines(Map { - return new SkiaCanvas(); - }) + new RenderEngineFactory(true, () => new SkiaCanvas()) ); renderEngines.Set( "gdi", - new RenderEngineFactory(true, () => { - return new GdiCanvas(); - }) + new RenderEngineFactory(true, () => new GdiCanvas()) ); renderEngines.Set("default", renderEngines.Get("skia")!); } diff --git a/src.csharp/AlphaTab/Io/TypeConversions.cs b/src.csharp/AlphaTab/Io/TypeConversions.cs new file mode 100644 index 000000000..59cd4e082 --- /dev/null +++ b/src.csharp/AlphaTab/Io/TypeConversions.cs @@ -0,0 +1,30 @@ +namespace AlphaTab.Io +{ + internal static class TypeConversions + { + public static double Int32ToUint16(double v) + { + return (ushort)(int)v; + } + + public static double Int32ToInt16(double v) + { + return (short)(int)v; + } + + public static double Int32ToUint32(double v) + { + return (uint)(int)v; + } + + public static double Uint16ToInt16(double v) + { + return (short)(ushort)(int)v; + } + + public static double Int16ToUint32(double v) + { + return (uint)(short)(int)v; + } + } +} diff --git a/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs b/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs index 5b8bc7fc2..076ee3cda 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs @@ -10,13 +10,15 @@ internal abstract class AlphaSynthWorkerApiBase : IAlphaSynth { private readonly ISynthOutput _output; private LogLevel _logLevel; + private double _bufferTimeInMilliseconds; protected AlphaSynth Player; - protected AlphaSynthWorkerApiBase(ISynthOutput output, LogLevel logLevel) + protected AlphaSynthWorkerApiBase(ISynthOutput output, LogLevel logLevel, double bufferTimeInMilliseconds) { _output = output; _logLevel = logLevel; + _bufferTimeInMilliseconds = bufferTimeInMilliseconds; Player = null!; } @@ -26,7 +28,7 @@ protected AlphaSynthWorkerApiBase(ISynthOutput output, LogLevel logLevel) protected void Initialize() { - Player = new AlphaSynth(_output); + Player = new AlphaSynth(_output, _bufferTimeInMilliseconds); Player.PositionChanged.On(OnPositionChanged); Player.StateChanged.On(OnStateChanged); Player.Finished.On(OnFinished); @@ -36,6 +38,7 @@ protected void Initialize() Player.MidiLoadFailed.On(OnMidiLoadFailed); Player.ReadyForPlayback.On(OnReadyForPlayback); Player.MidiEventsPlayed.On(OnMidiEventsPlayed); + Player.PlaybackRangeChanged.On(OnPlaybackRangeChanged); DispatchOnUiThread(OnReady); } @@ -186,6 +189,7 @@ public void SetChannelVolume(double channel, double volume) public IEventEmitterOfT StateChanged { get; } = new EventEmitterOfT(); public IEventEmitterOfT PositionChanged { get; } = new EventEmitterOfT(); public IEventEmitterOfT MidiEventsPlayed { get; } = new EventEmitterOfT(); + public IEventEmitterOfT PlaybackRangeChanged { get; } = new EventEmitterOfT(); protected virtual void OnReady() { @@ -236,5 +240,10 @@ protected virtual void OnPositionChanged(PositionChangedEventArgs obj) { DispatchOnUiThread(() => ((EventEmitterOfT)PositionChanged).Trigger(obj)); } + + protected virtual void OnPlaybackRangeChanged(PlaybackRangeChangedEventArgs obj) + { + DispatchOnUiThread(() => ((EventEmitterOfT)PlaybackRangeChanged).Trigger(obj)); + } } } diff --git a/src.csharp/AlphaTab/Platform/CSharp/GdiCanvas.cs b/src.csharp/AlphaTab/Platform/CSharp/GdiCanvas.cs index e3c8bd361..7dd99a156 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/GdiCanvas.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/GdiCanvas.cs @@ -19,9 +19,32 @@ internal sealed class GdiCanvas : ICanvas { private static readonly Graphics MeasurementGraphics; private static readonly PrivateFontCollection MusicFontCollection; + private static readonly PrivateFontCollection CustomFontCollection = new PrivateFontCollection(); + private static readonly IDictionary CustomFontFamilies = + new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly StringFormat MusicFontFormat; private static readonly StringFormat MusicFontFormatCenter; + public static void RegisterCustomFont(byte[] data) + { + var dataPtr = Marshal.AllocCoTaskMem(data.Length); + try + { + Marshal.Copy(data, 0, dataPtr, data.Length); + CustomFontCollection.AddMemoryFont(dataPtr, data.Length); + + CustomFontFamilies.Clear(); + foreach (var family in CustomFontCollection.Families) + { + CustomFontFamilies[family.Name] = family; + } + } + finally + { + Marshal.FreeCoTaskMem(dataPtr); + } + } + static GdiCanvas() { var measurementImage = new Bitmap(1, 1); @@ -134,19 +157,11 @@ public Model.Font Font { get { - var fs = Model.FontStyle.Plain; - if (_font.Bold) - { - fs = Model.FontStyle.Bold; - } - - if (_font.Italic) - { - fs = Model.FontStyle.Italic; - } + var fw = _font.Bold ? Model.FontWeight.Bold : Model.FontWeight.Regular; + var fs = _font.Italic ? Model.FontStyle.Italic : Model.FontStyle.Plain; return new Model.Font(_font.FontFamily.Name, _font.Size * Settings.Display.Scale, - fs); + fs, fw); } set { @@ -161,9 +176,19 @@ public Model.Font Font fontStyle = GdiFontStyle.Italic; } - _font = new GdiFont(value.Family, (float) (value.Size * Settings.Display.Scale), - fontStyle, - GraphicsUnit.Pixel); + if (CustomFontFamilies.TryGetValue(value.Family, out var gdiFamily)) + { + _font = new GdiFont(gdiFamily, (float) (value.Size * Settings.Display.Scale), + fontStyle, + GraphicsUnit.Pixel); + + } + else + { + _font = new GdiFont(value.Family, (float) (value.Size * Settings.Display.Scale), + fontStyle, + GraphicsUnit.Pixel); + } } } @@ -356,7 +381,7 @@ public void FillCircle(double x, double y, double radius) _currentY = y; Fill(); } - + public void StrokeCircle(double x, double y, double radius) { _currentPath.StartFigure(); diff --git a/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadAlphaSynthWorkerApi.cs b/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadAlphaSynthWorkerApi.cs index d3ee39dc2..612b18811 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadAlphaSynthWorkerApi.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadAlphaSynthWorkerApi.cs @@ -13,8 +13,8 @@ internal class ManagedThreadAlphaSynthWorkerApi : AlphaSynthWorkerApiBase private CancellationTokenSource _workerCancellationToken; private readonly ManualResetEventSlim? _threadStartedEvent; - public ManagedThreadAlphaSynthWorkerApi(ISynthOutput output, LogLevel logLevel, Action uiInvoke) - : base(output, logLevel) + public ManagedThreadAlphaSynthWorkerApi(ISynthOutput output, LogLevel logLevel, Action uiInvoke, double bufferTimeInMilliseconds) + : base(output, logLevel, bufferTimeInMilliseconds) { _uiInvoke = uiInvoke; diff --git a/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadScoreRenderer.cs b/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadScoreRenderer.cs index 4d4eb2100..d89019bfb 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadScoreRenderer.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/ManagedThreadScoreRenderer.cs @@ -2,7 +2,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; -using AlphaTab.Core; using AlphaTab.Core.EcmaScript; using AlphaTab.Model; using AlphaTab.Rendering; @@ -15,9 +14,9 @@ internal class ManagedThreadScoreRenderer : IScoreRenderer private readonly Action _uiInvoke; private readonly Thread _workerThread; - private BlockingCollection _workerQueue; - private ManualResetEventSlim? _threadStartedEvent; - private CancellationTokenSource _workerCancellationToken; + private readonly BlockingCollection _workerQueue; + private readonly ManualResetEventSlim? _threadStartedEvent; + private readonly CancellationTokenSource _workerCancellationToken; private ScoreRenderer _renderer; private double _width; @@ -31,8 +30,10 @@ public ManagedThreadScoreRenderer(Settings settings, Action uiInvoke) _workerQueue = new BlockingCollection(); _workerCancellationToken = new CancellationTokenSource(); - _workerThread = new Thread(DoWork); - _workerThread.IsBackground = true; + _workerThread = new Thread(DoWork) + { + IsBackground = true + }; _workerThread.Start(); _threadStartedEvent.Wait(); @@ -47,7 +48,7 @@ private void DoWork() { _threadStartedEvent.Set(); while (_workerQueue.TryTake(out var action, Timeout.Infinite, - _workerCancellationToken.Token)) + _workerCancellationToken.Token)) { if (_workerCancellationToken.IsCancellationRequested) { @@ -63,6 +64,8 @@ private void Initialize(Settings settings) _renderer = new ScoreRenderer(settings); _renderer.PartialRenderFinished.On(result => _uiInvoke(() => OnPartialRenderFinished(result))); + _renderer.PartialLayoutFinished.On(result => + _uiInvoke(() => OnPartialLayoutFinished(result))); _renderer.RenderFinished.On(result => _uiInvoke(() => OnRenderFinished(result))); _renderer.PostRenderFinished.On(() => _uiInvoke(() => OnPostFinished(_renderer.BoundsLookup))); @@ -111,6 +114,18 @@ public void Render() } } + public void RenderResult(string resultId) + { + if (CheckAccess()) + { + _renderer.RenderResult(resultId); + } + else + { + _workerQueue.Add(() => RenderResult(resultId)); + } + } + public double Width { get => _width; @@ -140,7 +155,7 @@ public void ResizeRender() } } - public void RenderScore(Score score, IList trackIndexes) + public void RenderScore(Score? score, IList? trackIndexes) { if (CheckAccess()) { @@ -148,7 +163,9 @@ public void RenderScore(Score score, IList trackIndexes) } else { - _workerQueue.Add(() => RenderScore(score, trackIndexes)); + _workerQueue.Add(() => + RenderScore(score, + trackIndexes)); } } @@ -156,7 +173,7 @@ public void RenderScore(Score score, IList trackIndexes) protected virtual void OnPreRender(bool isResize) { - ((EventEmitterOfT) PreRender).Trigger(isResize); + ((EventEmitterOfT)PreRender).Trigger(isResize); } public IEventEmitterOfT PartialRenderFinished { get; } = @@ -164,7 +181,15 @@ protected virtual void OnPreRender(bool isResize) protected virtual void OnPartialRenderFinished(RenderFinishedEventArgs obj) { - ((EventEmitterOfT) PartialRenderFinished).Trigger(obj); + ((EventEmitterOfT)PartialRenderFinished).Trigger(obj); + } + + public IEventEmitterOfT PartialLayoutFinished { get; } = + new EventEmitterOfT(); + + protected virtual void OnPartialLayoutFinished(RenderFinishedEventArgs obj) + { + ((EventEmitterOfT)PartialLayoutFinished).Trigger(obj); } public IEventEmitterOfT RenderFinished { get; } = @@ -172,21 +197,21 @@ protected virtual void OnPartialRenderFinished(RenderFinishedEventArgs obj) protected virtual void OnRenderFinished(RenderFinishedEventArgs obj) { - ((EventEmitterOfT) RenderFinished).Trigger(obj); + ((EventEmitterOfT)RenderFinished).Trigger(obj); } public IEventEmitterOfT Error { get; } = new EventEmitterOfT(); protected virtual void OnError(Error details) { - ((EventEmitterOfT) Error).Trigger(details); + ((EventEmitterOfT)Error).Trigger(details); } public IEventEmitter PostRenderFinished { get; } = new EventEmitter(); protected virtual void OnPostRenderFinished() { - ((EventEmitter) PostRenderFinished).Trigger(); + ((EventEmitter)PostRenderFinished).Trigger(); } } } diff --git a/src.csharp/AlphaTab/Platform/CSharp/ManagedUiFacade.cs b/src.csharp/AlphaTab/Platform/CSharp/ManagedUiFacade.cs index fd60462eb..fee25eb02 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/ManagedUiFacade.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/ManagedUiFacade.cs @@ -44,7 +44,7 @@ public IScoreRenderer CreateWorkerRenderer() public IAlphaSynth CreateWorkerPlayer() { var player = new ManagedThreadAlphaSynthWorkerApi(CreateSynthOutput(), - Api.Settings.Core.LogLevel, BeginInvoke); + Api.Settings.Core.LogLevel, BeginInvoke, Api.Settings.Player.BufferTimeInMilliseconds); player.Ready.On(() => { using (var sf = OpenDefaultSoundFont()) @@ -87,11 +87,12 @@ public virtual void InitialRender() protected abstract void RenderTracks(); public abstract void BeginAppendRenderResults(RenderFinishedEventArgs? renderResults); + public abstract void BeginUpdateRenderResults(RenderFinishedEventArgs? renderResults); public abstract void DestroyCursors(); public abstract Cursors? CreateCursors(); public abstract void BeginInvoke(Action action); public abstract void RemoveHighlights(); - public abstract void HighlightElements(string groupId); + public abstract void HighlightElements(string groupId, double masterBarIndex); public abstract IContainer? CreateSelectionElement(); public abstract IContainer GetScrollContainer(); public abstract Bounds GetOffset(IContainer? scrollElement, IContainer container); diff --git a/src.csharp/AlphaTab/Platform/CSharp/SkiaCanvas.cs b/src.csharp/AlphaTab/Platform/CSharp/SkiaCanvas.cs index 6a250e7f6..140162cab 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/SkiaCanvas.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/SkiaCanvas.cs @@ -2,90 +2,88 @@ using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using AlphaTab.Model; -using AlphaTab.Rendering.Glyphs; +using HarfBuzzSharp; using SkiaSharp; +using Font = AlphaTab.Model.Font; +using Math = System.Math; using String = AlphaTab.Core.EcmaScript.String; namespace AlphaTab.Platform.CSharp { - internal class SkiaCanvas : ICanvas + internal sealed class SkiaCanvas : ICanvas { private static readonly SKTypeface MusicFont; - private static readonly int MusicFontSize = 34; - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - private static extern IntPtr LoadLibrary(string libname); + private const int MusicFontSize = 34; static SkiaCanvas() { - // https://github.com/mono/SkiaSharp/issues/713 - // https://github.com/mono/SkiaSharp/issues/572 - // manually load skia lib - switch (System.Environment.OSVersion.Platform) - { - case PlatformID.MacOSX: - case PlatformID.Unix: - // I think unix platforms should be fine, to be tested - break; - default: - var libSkiaSharpPath = Path.GetDirectoryName(typeof(SkiaCanvas).Assembly.Location); - if (IntPtr.Size == 4) - { - libSkiaSharpPath = Path.Combine(libSkiaSharpPath, "runtimes", "win-x86", "native", "libSkiaSharp.dll"); - } - else - { - libSkiaSharpPath = Path.Combine(libSkiaSharpPath, "runtimes", "win-x64", "native", "libSkiaSharp.dll"); - } - - Logger.Debug("Skia", "Loading native lib from '" + libSkiaSharpPath + "'"); - var lib = LoadLibrary(libSkiaSharpPath); - if (lib == IntPtr.Zero) - { - Logger.Warning("Skia", "Loading native lib from '" + libSkiaSharpPath + "' failed"); - } - else - { - Logger.Debug("Skia", "Loading native lib from '" + libSkiaSharpPath + "' successful"); - } - - break; - } - // attempt to load correct skia native lib var type = typeof(SkiaCanvas).GetTypeInfo(); - using var bravura = type.Assembly.GetManifestResourceStream(type.Namespace + ".Bravura.ttf"); + using var bravura = + type.Assembly.GetManifestResourceStream(type.Namespace + ".Bravura.ttf"); MusicFont = SKTypeface.FromStream(bravura); } - private SKSurface _surface = null!; - private SKPath _path = null!; + private static readonly IDictionary CustomTypeFaces = + new Dictionary(StringComparer.OrdinalIgnoreCase); + public static void RegisterCustomFont(byte[] data) + { + using var skData = SKData.CreateCopy(data); + var face = SKTypeface.FromData(skData); + CustomTypeFaces[CustomTypeFaceKey(face)] = face; + } + + private static string CustomTypeFaceKey(SKTypeface typeface) + { + return CustomTypeFaceKey(typeface.FamilyName, typeface.FontWeight > 400, + typeface.FontSlant == SKFontStyleSlant.Italic); + } + + private static string CustomTypeFaceKey(string fontFamily, bool isBold, bool isItalic) + { + return fontFamily.ToLowerInvariant() + "_" + isBold + "_" + isItalic; + } + + private SKSurface? _surface; + private SKPath? _path; private string _typeFaceCache = ""; - private SKTypeface _typeFace = null!; + private bool _typeFaceIsSystem = false; + private SKTypeface? _typeFace; public Color Color { get; set; } public double LineWidth { get; set; } public Font Font { get; set; } - public SKTypeface TypeFace + private SKTypeface TypeFace { get { if (_typeFaceCache != Font.ToCssString(Settings.Display.Scale)) { - if (_typeFace != null) + if (_typeFaceIsSystem) { - _typeFace.Dispose(); + _typeFace?.Dispose(); } - _typeFaceCache = Font.ToCssString(Settings.Display.Scale); - _typeFace = SKTypeface.FromFamilyName(Font.Family, - Font.IsBold ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal, - SKFontStyleWidth.Normal, - Font.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright - ); + + var key = CustomTypeFaceKey(Font.Family, Font.IsBold, Font.IsItalic); + if (!CustomTypeFaces.TryGetValue(key, out _typeFace)) + { + _typeFaceIsSystem = true; + _typeFace = SKTypeface.FromFamilyName(Font.Family, + Font.IsBold ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal, + SKFontStyleWidth.Normal, + Font.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright + ); + } + else + { + _typeFaceIsSystem = false; + } } return _typeFace; @@ -109,19 +107,14 @@ public SkiaCanvas() public void BeginRender(double width, double height) { - var newImage = SKSurface.Create(new SKImageInfo((int)width, - (int)height, + var newImage = SKSurface.Create(new SKImageInfo((int) width, + (int) height, SKImageInfo.PlatformColorType, SKAlphaType.Premul)); _surface = newImage; - if (_path != null) - { - _path.Dispose(); - } - - _path = new SKPath(); - _path.FillType = SKPathFillType.Winding; + _path?.Dispose(); + _path = new SKPath {FillType = SKPathFillType.Winding}; } public object EndRender() @@ -131,7 +124,7 @@ public object EndRender() return image; } - public virtual object OnRenderFinished() + public object OnRenderFinished() { // nothing to do return null; @@ -139,33 +132,36 @@ public virtual object OnRenderFinished() public void FillRect(double x, double y, double w, double h) { - using (var paint = CreatePaint()) - { - paint.BlendMode = SKBlendMode.SrcOver; - _surface.Canvas.DrawRect(SKRect.Create((float)x, (float)y, (float)w, (float)h), paint); - } + using var paint = CreatePaint(); + paint.Style = SKPaintStyle.Fill; + _surface.Canvas.DrawRect(SKRect.Create((int) x, (int) y, (float) w, (float) h), + paint); } private SKPaint CreatePaint() { - var paint = new SKPaint(); - paint.IsAntialias = true; - paint.SubpixelText = true; - paint.DeviceKerningEnabled = true; - paint.Color = new SKColor((byte) Color.R, (byte) Color.G, (byte) Color.B, - (byte) Color.A); - return paint; + return new SKPaint + { + Color = new SKColor((byte) Color.R, (byte) Color.G, (byte) Color.B, + (byte) Color.A), + StrokeWidth = (float) LineWidth, + StrokeMiter = 4, + BlendMode = SKBlendMode.SrcOver, + IsAntialias = true, + IsDither = true, + StrokeCap = SKStrokeCap.Butt, + StrokeJoin = SKStrokeJoin.Miter, + FilterQuality = SKFilterQuality.None + }; } public void StrokeRect(double x, double y, double w, double h) { - using (var paint = CreatePaint()) - { - paint.BlendMode = SKBlendMode.SrcOver; - paint.StrokeWidth = (float)LineWidth; - paint.IsStroke = true; - _surface.Canvas.DrawRect(SKRect.Create((float)x, (float)y, (float)w, (float)h), paint); - } + using var paint = CreatePaint(); + paint.Style = SKPaintStyle.Stroke; + paint.StrokeWidth = (float) LineWidth; + _surface.Canvas.DrawRect(SKRect.Create((int) x, (int) y, (float) w, (float) h), + paint); } public void BeginPath() @@ -180,28 +176,30 @@ public void ClosePath() public void MoveTo(double x, double y) { - _path.MoveTo((float)x, (float)y); + _path.MoveTo((float) x, (float) y); } public void LineTo(double x, double y) { - _path.LineTo((float)x, (float)y); + _path.LineTo((float) x, (float) y); } public void QuadraticCurveTo(double cpx, double cpy, double x, double y) { - _path.QuadTo((float)cpx, (float)cpy, (float)x, (float)y); + _path.QuadTo((float) cpx, (float) cpy, (float) x, (float) y); } - public void BezierCurveTo(double cp1X, double cp1Y, double cp2X, double cp2Y, double x, double y) + public void BezierCurveTo(double cp1X, double cp1Y, double cp2X, double cp2Y, double x, + double y) { - _path.CubicTo((float)cp1X, (float)cp1Y, (float)cp2X, (float)cp2Y, (float)x, (float)y); + _path.CubicTo((float) cp1X, (float) cp1Y, (float) cp2X, (float) cp2Y, (float) x, + (float) y); } public void FillCircle(double x, double y, double radius) { BeginPath(); - _path.AddCircle((float)x, (float)y, (float)radius); + _path.AddCircle((float) x, (float) y, (float) radius); ClosePath(); Fill(); } @@ -209,7 +207,7 @@ public void FillCircle(double x, double y, double radius) public void StrokeCircle(double x, double y, double radius) { BeginPath(); - _path.AddCircle((float)x, (float)y, (float)radius); + _path.AddCircle((float) x, (float) y, (float) radius); ClosePath(); Stroke(); } @@ -218,6 +216,7 @@ public void Fill() { using (var paint = CreatePaint()) { + paint.Style = SKPaintStyle.Fill; _surface.Canvas.DrawPath(_path, paint); } @@ -228,8 +227,8 @@ public void Stroke() { using (var paint = CreatePaint()) { - paint.StrokeWidth = (float)LineWidth; - paint.IsStroke = true; + paint.Style = SKPaintStyle.Stroke; + paint.StrokeWidth = (float) LineWidth; _surface.Canvas.DrawPath(_path, paint); } @@ -244,75 +243,255 @@ public void EndGroup() { } - public void FillText(string text, double x, double y) + private const int SkiaToHarfBuzzFontSize = 1 << 16; + private const float HarfBuzzToSkiaFontSize = 1f / SkiaToHarfBuzzFontSize; + + [HandleProcessCorruptedStateExceptions] + private static HarfBuzzSharp.Font MakeHarfBuzzFont(SKTypeface typeface, int size) { - using (var paint = CreatePaint()) + try { - paint.Typeface = TypeFace; - paint.TextSize = (float)(Font.Size * Settings.Display.Scale); - switch (TextAlign) + using var stream = typeface.OpenStream(out var ttcIndex); + var data = Marshal.AllocCoTaskMem(stream.Length); + stream.Read(data, stream.Length); + using var blob = new Blob(data, stream.Length, MemoryMode.ReadOnly, + () => { Marshal.FreeCoTaskMem(data); }); + blob.MakeImmutable(); + + using var face = new Face(blob, ttcIndex) { - case TextAlign.Left: - paint.TextAlign = SKTextAlign.Left; - break; - case TextAlign.Center: - paint.TextAlign = SKTextAlign.Center; - break; - case TextAlign.Right: - paint.TextAlign = SKTextAlign.Right; - break; - } + Index = ttcIndex, + UnitsPerEm = typeface.UnitsPerEm + }; + + var font = new HarfBuzzSharp.Font(face); + var scale = size * SkiaToHarfBuzzFontSize; + font.SetScale(scale, scale); + font.SetFunctionsOpenType(); + return font; + } + catch (AccessViolationException e) + { + throw; + } + } + + + public void FillText(string text, double x, double y) + { + if (text.Length == 0) + { + return; + } + + TextRun(text, TypeFace, Font.Size, (blob, font, paint, width) => + { + var xOffset = GetFontOffset( + TextAlign, + width + ); + + var fontBaseLine = GetFontBaseLine( + TextBaseline, + font + ); + + _surface.Canvas.DrawText( + blob, + (float) x + xOffset, + (float) y + fontBaseLine, + paint + ); + }); + } + + private float GetFontOffset(TextAlign textAlign, float width) + { + return textAlign switch + { + TextAlign.Left => 0, + TextAlign.Center => -width / 2, + TextAlign.Right => -width, + _ => 0 + }; + } - _surface.Canvas.DrawText(text, (int)x, (int)y + GetFontBaseline(TextBaseline, paint), paint); + private void TextRun(string text, SKTypeface typeFace, double size, + Action action) + { + using var paint = CreatePaint(); + paint.Style = SKPaintStyle.Fill; + paint.Typeface = typeFace; + paint.TextSize = (float) (size * Settings.Display.Scale); + + using var harfBuzzFont = MakeHarfBuzzFont(typeFace, (int) size); + using var buffer = new HarfBuzzSharp.Buffer + { + Direction = Direction.LeftToRight, + Language = Language.Default + }; + buffer.AddUtf8(text); + harfBuzzFont.Shape(buffer); + + var infos = buffer.GlyphInfos; + var positions = buffer.GlyphPositions; + + using var skFont = paint.ToFont(); + skFont.Edging = SKFontEdging.Antialias; + skFont.Subpixel = true; + skFont.Hinting = SKFontHinting.Normal; + skFont.Typeface = typeFace; + skFont.Size = (float) size; + + using var blobBuilder = new SKTextBlobBuilder(); + var runBuffer = blobBuilder.AllocatePositionedRun(skFont, infos.Length); + + var glyphSpan = runBuffer.GetGlyphSpan(); + var positionSpan = runBuffer.GetPositionSpan(); + + var width = 0.0f; + for (var i = 0; i < infos.Length; i++) + { + glyphSpan[i] = (ushort) infos[i].Codepoint; + + var xOffset = width + HarfBuzzToSkiaFontSize * positions[i].XOffset; + var yOffset = HarfBuzzToSkiaFontSize * -positions[i].YOffset; + positionSpan[i] = new SKPoint(xOffset, yOffset); + + width += HarfBuzzToSkiaFontSize * positions[i].XAdvance; } + + using var blob = blobBuilder.Build(); + action(blob, skFont, paint, width); } - private float GetFontBaseline(TextBaseline baseline, SKPaint paint) + private const int HangingAsPercentOfAscent = 80; + + private float GetFontBaseLine(TextBaseline baseline, SKFont font) { + // TextMetrics::GetFontBaseline + // https://github.com/chromium/chromium/blob/99314be8152e688bafbbf9a615536bdbb289ea87/third_party/blink/renderer/core/html/canvas/text_metrics.cc#L14 switch (baseline) { - case TextBaseline.Top: // TopTextBaseline - // https://chromium.googlesource.com/chromium/blink/+/master/Source/modules/canvas2d/CanvasRenderingContext2D.cpp#2056 - // According to http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling - // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of the ascender height" - return (-paint.FontMetrics.Ascent * 4) / 5; - case TextBaseline.Middle: // MiddleTextBaseline - return -paint.FontMetrics.Descent + paint.TextSize / 2; - case TextBaseline.Bottom: // BottomTextBaseline - return -paint.FontMetrics.Descent; + case TextBaseline.Top: // Hanging + { + return FloatAscent(font.Metrics) * HangingAsPercentOfAscent / 100.0f; + } + case TextBaseline.Middle: + { + var (emHeightAscent, emHeightDescent) = EmHeightAscentDescent(font); + return (emHeightAscent - emHeightDescent) / 2.0f; + } + case TextBaseline.Bottom: + { + var (_, emHeightDescent) = EmHeightAscentDescent(font); + return -emHeightDescent; + } default: - break; + return 0; } + } - return 0; + private (float ascent, float descent) EmHeightAscentDescent(SKFont font) + { + var typeface = font.Typeface; + var (typoAscent, typeDecent) = TypoAscenderDescender(typeface); + if (typoAscent > 0 && + NormalizeEmHeightMetrics(font, typoAscent, typoAscent + typeDecent, + out var normTypoAsc, out var normTypoDesc)) + { + return (normTypoAsc, normTypoDesc); + } + + var metricAscent = FloatAscent(font.Metrics); + var metricDescent = FloatDescent(font.Metrics); + if (NormalizeEmHeightMetrics(font, metricAscent, metricAscent + metricDescent, + out var normAsc, out var normDesc)) + { + return (normAsc, normDesc); + } + + throw new InvalidOperationException("Cannot compute ascent and descent"); } - public double MeasureText(string text) + private bool NormalizeEmHeightMetrics(SKFont font, float ascent, float height, + out float emHeightAscent, out float emHeightDescent) { - if (string.IsNullOrEmpty(text)) + if (height <= 0 || ascent < 0 || ascent > height) { - return 0; + emHeightAscent = float.NaN; + emHeightDescent = float.NaN; + return false; } - using (var paint = CreatePaint()) + var emHeight = font.Size; + emHeightAscent = ascent * emHeight / height; + emHeightDescent = emHeight - emHeightAscent; + return true; + } + + private (short typoAscender, short typooDescender) TypoAscenderDescender( + SKTypeface typeface) + { + try { - paint.Typeface = TypeFace; - paint.TextSize = (float)Font.Size; - switch (TextAlign) + var buffer = typeface.GetTableData(GetIntTag("OS/2")); + if (buffer.Length >= 72) { - case TextAlign.Left: - paint.TextAlign = SKTextAlign.Left; - break; - case TextAlign.Center: - paint.TextAlign = SKTextAlign.Center; - break; - case TextAlign.Right: - paint.TextAlign = SKTextAlign.Right; - break; + return ( + (short) (buffer[68] << 8 | buffer[69]), + (short) -(buffer[70] << 8 | buffer[71]) + ); } + } + catch + { + // no data + } - return paint.MeasureText(text); + return (0, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float FloatAscent(SKFontMetrics metrics) + { + return SkScalarRoundToScalar(-metrics.Ascent); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float FloatDescent(SKFontMetrics metrics) + { + return SkScalarRoundToScalar(metrics.Descent); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float SkScalarRoundToScalar(float x) + { + return (float) Math.Floor(x + 0.5f); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint GetIntTag(string v) + { + return + (uint) v[0] << 24 | + (uint) v[1] << 16 | + (uint) v[2] << 08 | + (uint) v[3] << 00; + } + + public double MeasureText(string text) + { + if (string.IsNullOrEmpty(text)) + { + return 0; } + + var size = 0.0; + TextRun(text, TypeFace, Font.Size, + (blob, font, paint, width) => { size = width; }); + + return size; } public void FillMusicFontSymbol( @@ -327,17 +506,7 @@ public void FillMusicFontSymbol( return; } - using (var paint = CreatePaint()) - { - paint.Typeface = MusicFont; - paint.TextSize = (float)(MusicFontSize * scale); - if (centerAtPosition) - { - paint.TextAlign = SKTextAlign.Center; - } - - _surface.Canvas.DrawText(String.FromCharCode((double)symbol), (float)x, (float)y, paint); - } + FillMusicFontSymbols(x, y, scale, new[] {symbol}, centerAtPosition); } public void FillMusicFontSymbols( @@ -352,29 +521,30 @@ public void FillMusicFontSymbols( { if (symbol != MusicFontSymbol.None) { - s += String.FromCharCode((double)symbol); + s += String.FromCharCode((double) symbol); } } - using (var paint = CreatePaint()) + TextRun(s, MusicFont, MusicFontSize * scale, (blob, font, paint, width) => { - paint.Typeface = MusicFont; - paint.TextSize = (float)(MusicFontSize * scale); - if (centerAtPosition) - { - paint.TextAlign = SKTextAlign.Center; - } - - - _surface.Canvas.DrawText(s, (float)x, (float)y, paint); - } + var xOffset = GetFontOffset( + centerAtPosition ? TextAlign.Center : TextAlign.Left, + width); + + _surface.Canvas.DrawText( + blob, + (float) x + xOffset, + (float) y, + paint + ); + }); } public void BeginRotate(double centerX, double centerY, double angle) { _surface.Canvas.Save(); - _surface.Canvas.Translate((float)centerX, (float)centerY); - _surface.Canvas.RotateDegrees((float)angle); + _surface.Canvas.Translate((float) centerX, (float) centerY); + _surface.Canvas.RotateDegrees((float) angle); } public void EndRotate() diff --git a/src.csharp/AlphaTab/Platform/Svg/FontSizes.cs b/src.csharp/AlphaTab/Platform/Svg/FontSizes.cs index 1963d453c..f14645d3f 100644 --- a/src.csharp/AlphaTab/Platform/Svg/FontSizes.cs +++ b/src.csharp/AlphaTab/Platform/Svg/FontSizes.cs @@ -1,4 +1,5 @@ -using AlphaTab.Core.EcmaScript; +using AlphaTab.Core; +using AlphaTab.Core.EcmaScript; namespace AlphaTab.Platform.Svg { diff --git a/src.csharp/AlphaTab/Core/Lazy.cs b/src.csharp/AlphaTab/Util/Lazy.cs similarity index 95% rename from src.csharp/AlphaTab/Core/Lazy.cs rename to src.csharp/AlphaTab/Util/Lazy.cs index c412dc86f..3a1bfff78 100644 --- a/src.csharp/AlphaTab/Core/Lazy.cs +++ b/src.csharp/AlphaTab/Util/Lazy.cs @@ -1,4 +1,4 @@ -namespace AlphaTab.Core +namespace AlphaTab.Util { public class Lazy where T:class? { diff --git a/src.csharp/Directory.Build.props b/src.csharp/Directory.Build.props index 32de93ab8..b950aa09d 100644 --- a/src.csharp/Directory.Build.props +++ b/src.csharp/Directory.Build.props @@ -2,15 +2,15 @@ portable true - 1.2.2 - 1.2.2.0 + 1.2.3 + 1.2.3.0 $(AssemblyVersion) Danielku15 CoderLine AlphaTab en alphaTab is a cross platform music notation and guitar tablature rendering library. - Copyright © 2021, Daniel Kuschny and Contributors + Copyright © 2022, Daniel Kuschny and Contributors MPL-2.0 https://www.alphatab.net https://github.com/CoderLine/alphaTab diff --git a/src.csharp/Samples/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj b/src.csharp/Samples/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj deleted file mode 100644 index 68e4330bd..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Player/AlphaTab.Samples.Player.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - netcoreapp3.1 - Exe - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.Player/Program.cs b/src.csharp/Samples/AlphaTab.Samples.Player/Program.cs deleted file mode 100644 index 285bce071..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Player/Program.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.IO; -using AlphaTab.Midi; -using AlphaTab.Synth; -using AlphaTab.Importer; - -namespace AlphaTab.Samples.Player -{ - public static class Program - { - private static void Main(string[] args) - { - if (args.Length != 2) - { - Console.WriteLine("Usage AlphaTab.Samples.Player.exe PathToFile PathToSoundFont"); - return; - } - - // load score - var score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(args[0])); - - // generate midi - var midiFile = new MidiFile(); - var handler = new AlphaSynthMidiFileHandler(midiFile); - var generator = new MidiFileGenerator(score, null, handler); - generator.Generate(); - - var player = new AlphaSynth(new NAudioSynthOutput()); - player.MidiLoaded.On(() => { Console.WriteLine("Midi loaded"); }); - player.SoundFontLoaded.On(() => { Console.WriteLine("SoundFont loaded"); }); - player.MidiLoadFailed.On(e => { Console.WriteLine("Midi load failed"); }); - player.SoundFontLoadFailed.On(e => { Console.WriteLine("SoundFont load failed"); }); - player.Finished.On(() => - { - Console.WriteLine("Playback finished"); - ((NAudioSynthOutput) player.Output).Close(); - }); - player.PositionChanged.On(e => - { - var currentTime = TimeSpan.FromMilliseconds(e.CurrentTime); - var endTime = TimeSpan.FromMilliseconds(e.EndTime); - - Console.Write("\r{0:mm\\:ss\\:fff} ({1}) of {2:mm\\:ss\\:fff} ({3})", - currentTime, e.CurrentTick, endTime, e.EndTick); - }); - player.ReadyForPlayback.On(() => { Console.WriteLine("Ready for playback"); }); - player.LoadSoundFont(File.ReadAllBytes(args[1]), false); - player.LoadMidiFile(midiFile); - - Console.WriteLine("Start playing"); - player.Play(); - - Console.WriteLine("Press enter to exit"); - Console.ReadLine(); - - player.Pause(); - - Console.ReadLine(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Player/Properties/launchSettings.json b/src.csharp/Samples/AlphaTab.Samples.Player/Properties/launchSettings.json deleted file mode 100644 index 7e54006ee..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Player/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "AlphaTab.Samples.Player": { - "commandName": "Project", - "commandLineArgs": "$(SolutionDir)..\\test-data\\audio\\full-song.gp5 $(SolutionDir)..\\font\\sonivox\\sonivox.sf2" - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Player/Readme.md b/src.csharp/Samples/AlphaTab.Samples.Player/Readme.md deleted file mode 100644 index 50f20c3c6..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Player/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# AlphaTab PNG Dump Sample - -This sample reads a given input file and renders all tracks into PNG files. The PNG files are placed beside the input file. \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj b/src.csharp/Samples/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj deleted file mode 100644 index dcc78b990..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.PngDump/AlphaTab.Samples.PngDump.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - netcoreapp3.1 - Exe - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.PngDump/Program.cs b/src.csharp/Samples/AlphaTab.Samples.PngDump/Program.cs deleted file mode 100644 index f3e1a8dbb..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.PngDump/Program.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using AlphaTab.Importer; -using AlphaTab.Rendering; -using SkiaSharp; - -namespace AlphaTab.Samples.PngDump -{ - public static class Program - { - private static void Main(string[] args) - { - if (args.Length != 1) - { - Console.WriteLine("Usage AlphaTab.Samples.PngDump.exe Path"); - return; - } - - // load score - var score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(args[0])); - - // render score with svg engine and desired rendering width - var settings = new Settings(); - settings.Core.Engine = "skia"; - var renderer = new ScoreRenderer(settings) - { - Width = 970 - }; - - // iterate tracks - for (var i = 0; i < score.Tracks.Count; i++) - { - var track = score.Tracks[i]; - - // render track - Console.WriteLine("Rendering track {0} - {1}", i + 1, track.Name); - var images = new List(); - var totalWidth = 0; - var totalHeight = 0; - renderer.PartialRenderFinished.On(r => { images.Add((SKImage) r.RenderResult); }); - renderer.RenderFinished.On(r => - { - totalWidth = (int) r.TotalWidth; - totalHeight = (int) r.TotalHeight; - }); - renderer.RenderScore(score, new List {track.Index}); - - // write png - var info = new FileInfo(args[0]); - var path = Path.Combine(info.DirectoryName, - Path.GetFileNameWithoutExtension(info.Name) + "-" + i + ".png"); - - using var full = SKSurface.Create(new SKImageInfo(totalWidth, totalHeight, - SKImageInfo.PlatformColorType, SKAlphaType.Premul)); - - var y = 0; - foreach (var image in images) - { - full.Canvas.DrawImage(image, new SKRect(0, 0, image.Width, image.Height), - new SKRect(0, y, image.Width, y + image.Height)); - y += image.Height; - } - - using var fullImage = full.Snapshot(); - using var data = fullImage.Encode(SKEncodedImageFormat.Png, 100) - .AsStream(true); - using var fileStream = - new FileStream(path, FileMode.Create, FileAccess.Write); - data.CopyTo(fileStream); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.PngDump/Properties/launchSettings.json b/src.csharp/Samples/AlphaTab.Samples.PngDump/Properties/launchSettings.json deleted file mode 100644 index 90cb30469..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.PngDump/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "AlphaTab.Samples.PngDump": { - "commandName": "Project", - "commandLineArgs": "$(SolutionDir)..\\test-data\\audio\\full-song.gp5" - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.PngDump/Readme.md b/src.csharp/Samples/AlphaTab.Samples.PngDump/Readme.md deleted file mode 100644 index 50f20c3c6..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.PngDump/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# AlphaTab PNG Dump Sample - -This sample reads a given input file and renders all tracks into PNG files. The PNG files are placed beside the input file. \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj b/src.csharp/Samples/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj deleted file mode 100644 index dcc78b990..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/AlphaTab.Samples.ScoreDump.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - netcoreapp3.1 - Exe - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Program.cs b/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Program.cs deleted file mode 100644 index 8f4d1436c..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Program.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using AlphaTab.Importer; -using AlphaTab.Model; - -namespace AlphaTab.Samples.ScoreDump -{ - public static class Program - { - private static void Main(string[] args) - { - if (args.Length != 1) - { - Console.WriteLine("Usage AlphaTab.Samples.ScoreDump.exe Path"); - return; - } - - var score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(args[0])); - - // score info - Console.WriteLine("Title: {0}", score.Title); - Console.WriteLine("Subtitle: {0}", score.SubTitle); - Console.WriteLine("Artist: {0}", score.Artist); - Console.WriteLine("Tempo: {0}", score.Tempo); - Console.WriteLine("Bars: {0}", score.MasterBars.Count); - Console.WriteLine("Time Signature: {0}/{1}", score.MasterBars[0].TimeSignatureNumerator, - score.MasterBars[0].TimeSignatureDenominator); - // tracks - Console.WriteLine("Tracks: "); - for (var i = 0; i < score.Tracks.Count; i++) - { - var track = score.Tracks[i]; - Console.WriteLine(" {0} - {1} - {2}", i + 1, track.Name, - track.Staves.Any(s => s.IsPercussion) - ? "Percussion" - : "Midi Instrument: " + track.PlaybackInfo.Program); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Properties/launchSettings.json b/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Properties/launchSettings.json deleted file mode 100644 index 9ff5dda4f..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "AlphaTab.Samples.ScoreDump": { - "commandName": "Project", - "commandLineArgs": "$(SolutionDir)..\\test-data\\audio\\full-song.gp5" - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Readme.md b/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Readme.md deleted file mode 100644 index cff7ec5f9..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.ScoreDump/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# AlphaTab Score Dump Sample - -This sample reads a given input file and prints out basic information about the loaded file. \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj b/src.csharp/Samples/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj deleted file mode 100644 index c8b14b639..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/AlphaTab.Samples.WinForms.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - netcoreapp3.1 - true - WinExe - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/ColorTools.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/ColorTools.cs deleted file mode 100644 index 12f04d500..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/ColorTools.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Drawing; - -namespace AlphaTab.Samples.WinForms -{ - /// - /// http://www.geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm - /// - public static class ColorTools - { - // Given H,S,L in range of 0-1 - // Returns a Color (RGB struct) in range of 0-255 - public static Color HSL2RGB(double h, double sl, double l) - { - double v; - double r, g, b; - - r = l; // default to gray - g = l; - b = l; - v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl); - if (v > 0) - { - double m; - double sv; - int sextant; - double fract, vsf, mid1, mid2; - - m = l + l - v; - sv = (v - m) / v; - h *= 6.0; - sextant = (int)h; - fract = h - sextant; - vsf = v * sv * fract; - mid1 = m + vsf; - mid2 = v - vsf; - switch (sextant) - { - case 0: - r = v; - g = mid1; - b = m; - break; - case 1: - r = mid2; - g = v; - b = m; - break; - case 2: - r = m; - g = v; - b = mid1; - break; - case 3: - r = m; - g = mid2; - b = v; - break; - case 4: - r = mid1; - g = m; - b = v; - break; - case 5: - r = v; - g = m; - b = mid2; - break; - } - } - return Color.FromArgb(Convert.ToByte(r * 255.0f), Convert.ToByte(g * 255.0f), Convert.ToByte(b * 255.0f)); - } - - // Given a Color (RGB Struct) in range of 0-255 - // Return H,S,L in range of 0-1 - public static void RGB2HSL(Color rgb, out double h, out double s, out double l) - { - var r = rgb.R / 255.0; - var g = rgb.G / 255.0; - var b = rgb.B / 255.0; - double v; - double m; - double vm; - double r2, g2, b2; - - h = 0; // default to black - s = 0; - l = 0; - - v = System.Math.Max(r, g); - v = System.Math.Max(v, b); - m = System.Math.Min(r, g); - m = System.Math.Min(m, b); - l = (m + v) / 2.0; - if (l <= 0.0) - { - return; - } - vm = v - m; - s = vm; - if (s > 0.0) - { - s /= (l <= 0.5) ? (v + m) : (2.0 - v - m); - } - else - { - return; - } - r2 = (v - r) / vm; - g2 = (v - g) / vm; - b2 = (v - b) / vm; - if (r == v) - { - h = (g == m ? 5.0 + b2 : 1.0 - g2); - } - else if (g == v) - { - h = (b == m ? 1.0 + r2 : 3.0 - b2); - } - else - { - h = (r == m ? 3.0 + g2 : 5.0 - r2); - } - h /= 6.0; - } - - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.Designer.cs deleted file mode 100644 index 4a104b5c3..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.Designer.cs +++ /dev/null @@ -1,279 +0,0 @@ -using AlphaTab.WinForms; - -namespace AlphaTab.Samples.WinForms -{ - partial class MainWindow - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer(); - this.alphaTabControl1 = new AlphaTab.WinForms.AlphaTabControl(); - this.mainToolBar = new System.Windows.Forms.ToolStrip(); - this.openFileButton = new System.Windows.Forms.ToolStripButton(); - this.playPauseButton = new System.Windows.Forms.ToolStripButton(); - this.showScoreInfo = new System.Windows.Forms.ToolStripButton(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.panel2 = new System.Windows.Forms.Panel(); - this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); - this.panel3 = new System.Windows.Forms.Panel(); - this.trackDetails = new System.Windows.Forms.Panel(); - this.trackHeaderControl1 = new AlphaTab.Samples.WinForms.TrackHeaderControl(); - this.trackBars = new System.Windows.Forms.Panel(); - this.toolStripContainer1.ContentPanel.SuspendLayout(); - this.toolStripContainer1.TopToolStripPanel.SuspendLayout(); - this.toolStripContainer1.SuspendLayout(); - this.mainToolBar.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); - this.panel2.SuspendLayout(); - this.tableLayoutPanel2.SuspendLayout(); - this.panel3.SuspendLayout(); - this.SuspendLayout(); - // - // toolStripContainer1 - // - // - // toolStripContainer1.ContentPanel - // - this.toolStripContainer1.ContentPanel.Controls.Add(this.alphaTabControl1); - this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(891, 318); - this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.toolStripContainer1.LeftToolStripPanelVisible = false; - this.toolStripContainer1.Location = new System.Drawing.Point(0, 0); - this.toolStripContainer1.Name = "toolStripContainer1"; - this.toolStripContainer1.RightToolStripPanelVisible = false; - this.toolStripContainer1.Size = new System.Drawing.Size(891, 359); - this.toolStripContainer1.TabIndex = 0; - // - // toolStripContainer1.TopToolStripPanel - // - this.toolStripContainer1.TopToolStripPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); - this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.mainToolBar); - this.toolStripContainer1.TopToolStripPanel.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - // - // alphaTabControl1 - // - this.alphaTabControl1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(97)))), ((int)(((byte)(99)))), ((int)(((byte)(98))))); - this.alphaTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.alphaTabControl1.ForeColor = System.Drawing.Color.WhiteSmoke; - this.alphaTabControl1.Location = new System.Drawing.Point(0, 0); - this.alphaTabControl1.Name = "alphaTabControl1"; - this.alphaTabControl1.Padding = new System.Windows.Forms.Padding(10); - this.alphaTabControl1.Size = new System.Drawing.Size(891, 318); - this.alphaTabControl1.TabIndex = 0; - this.alphaTabControl1.Text = "alphaTabControl1"; - // - // mainToolBar - // - this.mainToolBar.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); - this.mainToolBar.Dock = System.Windows.Forms.DockStyle.None; - this.mainToolBar.ImageScalingSize = new System.Drawing.Size(24, 24); - this.mainToolBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.openFileButton, - this.showScoreInfo, - this.playPauseButton}); - this.mainToolBar.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; - this.mainToolBar.Location = new System.Drawing.Point(3, 0); - this.mainToolBar.Name = "mainToolBar"; - this.mainToolBar.Padding = new System.Windows.Forms.Padding(5); - this.mainToolBar.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - this.mainToolBar.Size = new System.Drawing.Size(189, 41); - this.mainToolBar.TabIndex = 0; - // - // openFileButton - // - this.openFileButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.openFileButton.Image = global::AlphaTab.Samples.WinForms.Properties.Resources.folder_page_white; - this.openFileButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.openFileButton.Name = "openFileButton"; - this.openFileButton.Size = new System.Drawing.Size(28, 28); - this.openFileButton.Text = "Open File"; - this.openFileButton.Click += new System.EventHandler(this.openFileButton_Click); - // - // playPauseButton - // - this.playPauseButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.playPauseButton.Image = global::AlphaTab.Samples.WinForms.Properties.Resources.control_play; - this.playPauseButton.Name = "playPauseButton"; - this.playPauseButton.Size = new System.Drawing.Size(28, 28); - this.playPauseButton.Text = "Play/Pause"; - this.playPauseButton.Click += new System.EventHandler(this.playPauseButton_Click); - // - // showScoreInfo - // - this.showScoreInfo.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.showScoreInfo.Enabled = false; - this.showScoreInfo.Image = global::AlphaTab.Samples.WinForms.Properties.Resources.information; - this.showScoreInfo.ImageTransparentColor = System.Drawing.Color.Magenta; - this.showScoreInfo.Name = "showScoreInfo"; - this.showScoreInfo.Size = new System.Drawing.Size(28, 28); - this.showScoreInfo.Text = "Show Score Info"; - this.showScoreInfo.Click += new System.EventHandler(this.showScoreInfo_Click); - // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; - this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Name = "splitContainer1"; - this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.toolStripContainer1); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(95)))), ((int)(((byte)(94))))); - this.splitContainer1.Panel2.Controls.Add(this.panel2); - this.splitContainer1.Size = new System.Drawing.Size(891, 590); - this.splitContainer1.SplitterDistance = 359; - this.splitContainer1.TabIndex = 2; - // - // panel2 - // - this.panel2.AutoScroll = true; - this.panel2.Controls.Add(this.tableLayoutPanel2); - this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel2.Location = new System.Drawing.Point(0, 0); - this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(891, 227); - this.panel2.TabIndex = 1; - // - // tableLayoutPanel2 - // - this.tableLayoutPanel2.AutoSize = true; - this.tableLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel2.ColumnCount = 2; - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 420F)); - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel2.Controls.Add(this.panel3, 0, 0); - this.tableLayoutPanel2.Controls.Add(this.trackBars, 1, 0); - this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 1; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(891, 39); - this.tableLayoutPanel2.TabIndex = 0; - // - // panel3 - // - this.panel3.AutoSize = true; - this.panel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.panel3.Controls.Add(this.trackDetails); - this.panel3.Controls.Add(this.trackHeaderControl1); - this.panel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel3.Location = new System.Drawing.Point(0, 0); - this.panel3.Margin = new System.Windows.Forms.Padding(0); - this.panel3.Name = "panel3"; - this.panel3.Size = new System.Drawing.Size(420, 39); - this.panel3.TabIndex = 1; - // - // trackDetails - // - this.trackDetails.AutoSize = true; - this.trackDetails.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.trackDetails.Dock = System.Windows.Forms.DockStyle.Fill; - this.trackDetails.Location = new System.Drawing.Point(0, 39); - this.trackDetails.Margin = new System.Windows.Forms.Padding(0); - this.trackDetails.Name = "trackDetails"; - this.trackDetails.Size = new System.Drawing.Size(420, 0); - this.trackDetails.TabIndex = 0; - // - // trackHeaderControl1 - // - this.trackHeaderControl1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(117)))), ((int)(((byte)(118)))), ((int)(((byte)(119))))); - this.trackHeaderControl1.Dock = System.Windows.Forms.DockStyle.Top; - this.trackHeaderControl1.Location = new System.Drawing.Point(0, 0); - this.trackHeaderControl1.Name = "trackHeaderControl1"; - this.trackHeaderControl1.Size = new System.Drawing.Size(420, 39); - this.trackHeaderControl1.TabIndex = 0; - // - // trackBars - // - this.trackBars.AutoSize = true; - this.trackBars.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.trackBars.Dock = System.Windows.Forms.DockStyle.Top; - this.trackBars.Location = new System.Drawing.Point(420, 0); - this.trackBars.Margin = new System.Windows.Forms.Padding(0); - this.trackBars.Name = "trackBars"; - this.trackBars.Padding = new System.Windows.Forms.Padding(0, 39, 0, 0); - this.trackBars.Size = new System.Drawing.Size(471, 39); - this.trackBars.TabIndex = 2; - // - // MainWindow - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(891, 590); - this.Controls.Add(this.splitContainer1); - this.Name = "MainWindow"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "AlphaTab"; - this.WindowState = System.Windows.Forms.FormWindowState.Maximized; - this.toolStripContainer1.ContentPanel.ResumeLayout(false); - this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false); - this.toolStripContainer1.TopToolStripPanel.PerformLayout(); - this.toolStripContainer1.ResumeLayout(false); - this.toolStripContainer1.PerformLayout(); - this.mainToolBar.ResumeLayout(false); - this.mainToolBar.PerformLayout(); - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); - this.panel2.ResumeLayout(false); - this.panel2.PerformLayout(); - this.tableLayoutPanel2.ResumeLayout(false); - this.tableLayoutPanel2.PerformLayout(); - this.panel3.ResumeLayout(false); - this.panel3.PerformLayout(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.ToolStripContainer toolStripContainer1; - private System.Windows.Forms.ToolStrip mainToolBar; - private System.Windows.Forms.ToolStripButton showScoreInfo; - private System.Windows.Forms.SplitContainer splitContainer1; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; - private System.Windows.Forms.Panel panel2; - private System.Windows.Forms.Panel trackDetails; - private System.Windows.Forms.Panel panel3; - private TrackHeaderControl trackHeaderControl1; - private System.Windows.Forms.Panel trackBars; - private System.Windows.Forms.ToolStripButton openFileButton; - private System.Windows.Forms.ToolStripButton playPauseButton; - private AlphaTabControl alphaTabControl1; - } -} - diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.cs deleted file mode 100644 index 4eef66c50..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.IO; -using System.Windows.Forms; -using AlphaTab.Synth; -using AlphaTab.Importer; -using AlphaTab.Model; -using AlphaTab.Samples.WinForms.Properties; -using Track = AlphaTab.Model.Track; - -namespace AlphaTab.Samples.WinForms -{ - public partial class MainWindow : Form - { - private Score _score; - private int _currentTrackIndex; - - public MainWindow() - { - InitializeComponent(); - alphaTabControl1.HandleCreated += (sender, args) => - { - alphaTabControl1.Api.Player.StateChanged.On(OnPlayerStateChanged); - }; - } - - - private void OnPlayerStateChanged(PlayerStateChangedEventArgs e) - { - switch (e.State) - { - case PlayerState.Paused: - playPauseButton.Image = Resources.control_play; - break; - case PlayerState.Playing: - playPauseButton.Image = Resources.control_pause; - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private void openFileButton_Click(object sender, EventArgs e) - { - OpenFile(); - } - - #region Score Data - - public Score Score - { - get => _score; - set - { - _score = value; - showScoreInfo.Enabled = value != null; - Text = "AlphaTab - " + (value == null ? "No File Opened" : value.Title); - CurrentTrackIndex = 0; - } - } - - public int CurrentTrackIndex - { - get => _currentTrackIndex; - set - { - _currentTrackIndex = value; - UpdateSelectedTrack(); - var track = CurrentTrack; - if (track != null) - { - alphaTabControl1.Tracks = new[] {track}; - } - } - } - - public Track CurrentTrack - { - get - { - if (Score == null || CurrentTrackIndex < 0 || - CurrentTrackIndex >= _score.Tracks.Count) - { - return null; - } - - return _score.Tracks[_currentTrackIndex]; - } - } - - #endregion - - #region Score Loading - - private void OpenFile() - { - using (var dialog = new OpenFileDialog()) - { - dialog.Filter = - "Supported Files (*.gp3, *.gp4, *.gp5, *.gpx, *.gp)|*.gp3;*.gp4;*.gp5;*.gpx;*.gp"; - if (dialog.ShowDialog(this) == DialogResult.OK) - { - OpenFile(dialog.FileName); - } - } - } - - private void OpenFile(string file) - { - if (!string.IsNullOrWhiteSpace(file) && File.Exists(file)) - { - InternalOpenFile(file); - } - } - - private void InternalOpenFile(string file) - { - try - { - // load the score from the filesystem - Score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(file)); - - trackDetails.Controls.Clear(); - trackBars.Controls.Clear(); - for (var i = Score.Tracks.Count - 1; i >= 0; i--) - { - var details = new TrackDetailsControl(Score.Tracks[i]); - details.Dock = DockStyle.Top; - details.Height = 25; - trackDetails.Controls.Add(details); - details.Selected += details_Click; - - var bars = new TrackBarsControl(Score.Tracks[i]); - bars.Dock = DockStyle.Top; - trackBars.Controls.Add(bars); - } - - UpdateSelectedTrack(); - } - catch (Exception e) - { - MessageBox.Show(this, e.Message, "An error during opening the file occured", - MessageBoxButtons.OK, - MessageBoxIcon.Error); - } - } - - private void details_Click(object sender, EventArgs e) - { - var details = (TrackDetailsControl) sender; - CurrentTrackIndex = _score.Tracks.IndexOf(details.Track); - } - - private void UpdateSelectedTrack() - { - var currentTrack = CurrentTrack; - foreach (TrackDetailsControl trackViewModel in trackDetails.Controls) - { - trackViewModel.IsSelected = currentTrack == trackViewModel.Track; - } - } - - #endregion - - private void showScoreInfo_Click(object sender, EventArgs e) - { - if (_score == null) - { - return; - } - - using (var window = new ScoreInfoWindow(_score)) - { - window.ShowDialog(this); - } - } - - private void playPauseButton_Click(object sender, EventArgs e) - { - alphaTabControl1.Api.PlayPause(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.resx b/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.resx deleted file mode 100644 index b693414f3..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/MainWindow.resx +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Program.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/Program.cs deleted file mode 100644 index 1eaadc10b..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Program.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Windows.Forms; - -namespace AlphaTab.Samples.WinForms -{ - internal static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - private static void Main() - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainWindow()); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.Designer.cs deleted file mode 100644 index f492be3df..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.Designer.cs +++ /dev/null @@ -1,113 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace AlphaTab.Samples.WinForms.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AlphaTab.Samples.WinForms.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap control_pause { - get { - object obj = ResourceManager.GetObject("control_pause", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap control_play { - get { - object obj = ResourceManager.GetObject("control_play", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap control_stop { - get { - object obj = ResourceManager.GetObject("control_stop", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap folder_page_white { - get { - object obj = ResourceManager.GetObject("folder_page_white", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap information { - get { - object obj = ResourceManager.GetObject("information", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.resx b/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.resx deleted file mode 100644 index daf2daab0..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Resources.resx +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\information.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\folder_page_white.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\control_pause.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\control_play.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\control_stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.Designer.cs deleted file mode 100644 index 8bae3fbb3..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace AlphaTab.Samples.WinForms.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.settings b/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.settings deleted file mode 100644 index 39645652a..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Readme.md b/src.csharp/Samples/AlphaTab.Samples.WinForms/Readme.md deleted file mode 100644 index e6e841217..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# AlphaTab WinForms Sample - -This sample uses GDI+ or SkiaSharp (user choice) as drawing engine and uses the WinForms Control to actually display the rendered image. \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_pause.png b/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_pause.png deleted file mode 100644 index 186f361f0..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_pause.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_play.png b/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_play.png deleted file mode 100644 index 3b64790b9..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_play.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_stop.png b/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_stop.png deleted file mode 100644 index e29637703..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/control_stop.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/folder_page_white.png b/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/folder_page_white.png deleted file mode 100644 index b20277a8f..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/folder_page_white.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/information.png b/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/information.png deleted file mode 100644 index 93c67f2bf..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.WinForms/Resources/information.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.Designer.cs deleted file mode 100644 index 470aaa0e1..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.Designer.cs +++ /dev/null @@ -1,275 +0,0 @@ -namespace AlphaTab.Samples.WinForms -{ - partial class ScoreInfoWindow - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.txtTitle = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.txtSubTitle = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.txtArtist = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.txtAlbum = new System.Windows.Forms.TextBox(); - this.label4 = new System.Windows.Forms.Label(); - this.txtLyrics = new System.Windows.Forms.TextBox(); - this.label5 = new System.Windows.Forms.Label(); - this.txtMusic = new System.Windows.Forms.TextBox(); - this.label6 = new System.Windows.Forms.Label(); - this.txtCopyright = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.txtTab = new System.Windows.Forms.TextBox(); - this.label8 = new System.Windows.Forms.Label(); - this.txtNotes = new System.Windows.Forms.TextBox(); - this.label9 = new System.Windows.Forms.Label(); - this.okButton = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // txtTitle - // - this.txtTitle.Enabled = false; - this.txtTitle.Location = new System.Drawing.Point(100, 12); - this.txtTitle.Name = "txtTitle"; - this.txtTitle.Size = new System.Drawing.Size(271, 20); - this.txtTitle.TabIndex = 0; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 15); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(27, 13); - this.label1.TabIndex = 1; - this.label1.Text = "Title"; - // - // txtSubTitle - // - this.txtSubTitle.Enabled = false; - this.txtSubTitle.Location = new System.Drawing.Point(100, 38); - this.txtSubTitle.Name = "txtSubTitle"; - this.txtSubTitle.Size = new System.Drawing.Size(271, 20); - this.txtSubTitle.TabIndex = 0; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 41); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(42, 13); - this.label2.TabIndex = 1; - this.label2.Text = "Subtitle"; - // - // txtArtist - // - this.txtArtist.Enabled = false; - this.txtArtist.Location = new System.Drawing.Point(100, 64); - this.txtArtist.Name = "txtArtist"; - this.txtArtist.Size = new System.Drawing.Size(271, 20); - this.txtArtist.TabIndex = 0; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(12, 67); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(30, 13); - this.label3.TabIndex = 1; - this.label3.Text = "Artist"; - // - // txtAlbum - // - this.txtAlbum.Enabled = false; - this.txtAlbum.Location = new System.Drawing.Point(100, 90); - this.txtAlbum.Name = "txtAlbum"; - this.txtAlbum.Size = new System.Drawing.Size(271, 20); - this.txtAlbum.TabIndex = 0; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(12, 93); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(36, 13); - this.label4.TabIndex = 1; - this.label4.Text = "Album"; - // - // txtLyrics - // - this.txtLyrics.Enabled = false; - this.txtLyrics.Location = new System.Drawing.Point(100, 116); - this.txtLyrics.Name = "txtLyrics"; - this.txtLyrics.Size = new System.Drawing.Size(271, 20); - this.txtLyrics.TabIndex = 0; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(12, 119); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(34, 13); - this.label5.TabIndex = 1; - this.label5.Text = "Lyrics"; - // - // txtMusic - // - this.txtMusic.Enabled = false; - this.txtMusic.Location = new System.Drawing.Point(100, 142); - this.txtMusic.Name = "txtMusic"; - this.txtMusic.Size = new System.Drawing.Size(271, 20); - this.txtMusic.TabIndex = 0; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(12, 145); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(35, 13); - this.label6.TabIndex = 1; - this.label6.Text = "Music"; - // - // txtCopyright - // - this.txtCopyright.Enabled = false; - this.txtCopyright.Location = new System.Drawing.Point(100, 168); - this.txtCopyright.Multiline = true; - this.txtCopyright.Name = "txtCopyright"; - this.txtCopyright.Size = new System.Drawing.Size(271, 100); - this.txtCopyright.TabIndex = 0; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(12, 213); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(51, 13); - this.label7.TabIndex = 1; - this.label7.Text = "Copyright"; - // - // txtTab - // - this.txtTab.Enabled = false; - this.txtTab.Location = new System.Drawing.Point(101, 274); - this.txtTab.Name = "txtTab"; - this.txtTab.Size = new System.Drawing.Size(271, 20); - this.txtTab.TabIndex = 0; - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(13, 277); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(26, 13); - this.label8.TabIndex = 1; - this.label8.Text = "Tab"; - // - // txtNotes - // - this.txtNotes.Enabled = false; - this.txtNotes.Location = new System.Drawing.Point(101, 300); - this.txtNotes.Multiline = true; - this.txtNotes.Name = "txtNotes"; - this.txtNotes.Size = new System.Drawing.Size(271, 100); - this.txtNotes.TabIndex = 0; - // - // label9 - // - this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(13, 345); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(35, 13); - this.label9.TabIndex = 1; - this.label9.Text = "Notes"; - // - // okButton - // - this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; - this.okButton.Location = new System.Drawing.Point(297, 406); - this.okButton.Name = "okButton"; - this.okButton.Size = new System.Drawing.Size(75, 23); - this.okButton.TabIndex = 2; - this.okButton.Text = "Ok"; - this.okButton.UseVisualStyleBackColor = true; - // - // ScoreInfoWindow - // - this.AcceptButton = this.okButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.okButton; - this.ClientSize = new System.Drawing.Size(384, 440); - this.Controls.Add(this.okButton); - this.Controls.Add(this.label9); - this.Controls.Add(this.label7); - this.Controls.Add(this.label8); - this.Controls.Add(this.label6); - this.Controls.Add(this.label5); - this.Controls.Add(this.label4); - this.Controls.Add(this.label3); - this.Controls.Add(this.label2); - this.Controls.Add(this.label1); - this.Controls.Add(this.txtNotes); - this.Controls.Add(this.txtCopyright); - this.Controls.Add(this.txtTab); - this.Controls.Add(this.txtMusic); - this.Controls.Add(this.txtLyrics); - this.Controls.Add(this.txtAlbum); - this.Controls.Add(this.txtArtist); - this.Controls.Add(this.txtSubTitle); - this.Controls.Add(this.txtTitle); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; - this.Name = "ScoreInfoWindow"; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Score Information"; - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label label1; - private System.Windows.Forms.TextBox txtSubTitle; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox txtArtist; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.TextBox txtAlbum; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox txtLyrics; - private System.Windows.Forms.Label label5; - private System.Windows.Forms.TextBox txtMusic; - private System.Windows.Forms.Label label6; - private System.Windows.Forms.TextBox txtCopyright; - private System.Windows.Forms.Label label7; - private System.Windows.Forms.TextBox txtTab; - private System.Windows.Forms.Label label8; - private System.Windows.Forms.TextBox txtNotes; - private System.Windows.Forms.Label label9; - private System.Windows.Forms.Button okButton; - private System.Windows.Forms.TextBox txtTitle; - } -} \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.cs deleted file mode 100644 index 02cbc4790..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Windows.Forms; -using AlphaTab.Model; - -namespace AlphaTab.Samples.WinForms -{ - public partial class ScoreInfoWindow : Form - { - public ScoreInfoWindow() - { - InitializeComponent(); - } - - public ScoreInfoWindow(Score score) - { - InitializeComponent(); - txtAlbum.Text = score.Album; - txtArtist.Text = score.Artist; - txtCopyright.Text = score.Copyright; - txtLyrics.Text = score.Words; - txtMusic.Text = score.Music; - txtNotes.Text = score.Notices; - txtSubTitle.Text = score.SubTitle; - txtTab.Text = score.Tab; - txtTitle.Text = score.Title; - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.resx b/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.resx deleted file mode 100644 index 1af7de150..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/ScoreInfoWindow.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackBarsControl.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackBarsControl.cs deleted file mode 100644 index b083ab046..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackBarsControl.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; -using AlphaTab.Model; -using Color = System.Drawing.Color; - -namespace AlphaTab.Samples.WinForms -{ - internal class TrackBarsControl : Control - { - private static readonly Size BlockSize = new Size(25, 25); - private readonly bool[] _usedBars; - private Color _startColor; - private Color _endColor; - - public TrackBarsControl(Track track) - { - SetStyle(ControlStyles.FixedHeight, true); - SetStyle(ControlStyles.DoubleBuffer, true); - SetStyle(ControlStyles.OptimizedDoubleBuffer, true); - SetStyle(ControlStyles.ResizeRedraw, true); - SetStyle(ControlStyles.UserPaint, true); - base.DoubleBuffered = true; - base.BackColor = Color.FromArgb(93, 95, 94); - - _usedBars = new bool[(int) track.Score.MasterBars.Count]; - for (var s = 0; s < track.Staves.Count; s++) - { - var staff = track.Staves[s]; - for (var barI = 0; barI < staff.Bars.Count; barI++) - { - var bar = staff.Bars[barI]; - _usedBars[barI] = false; - - for (var voiceI = 0; voiceI < bar.Voices.Count && (!_usedBars[barI]); voiceI++) - { - var voice = bar.Voices[voiceI]; - for (var i = 0; i < voice.Beats.Count; i++) - { - var b = voice.Beats[i]; - if (!b.IsRest) - { - _usedBars[barI] = true; - } - } - } - } - } - - PerformLayout(); - Width = BlockSize.Width * _usedBars.Length; - Height = BlockSize.Height; - MinimumSize = BlockSize; - - SetColor(track.Color); - } - - private void SetColor(Model.Color color) - { - var baseColor = Color.FromArgb((byte) color.R, (byte) color.G, (byte) color.B); - double h, s, l; - ColorTools.RGB2HSL(baseColor, out h, out s, out l); - - _startColor = ColorTools.HSL2RGB(h, System.Math.Max(0, System.Math.Min(1, s - 0.2)), - System.Math.Max(0, System.Math.Min(1, l + 0.2))); - _endColor = ColorTools.HSL2RGB(h, System.Math.Max(0, System.Math.Min(1, s - 0.2)), - System.Math.Max(0, System.Math.Min(1, l - 0.2))); - } - - protected override void OnPaint(PaintEventArgs e) - { - base.OnPaint(e); - if (_usedBars == null) - { - return; - } - - using (var brush = new LinearGradientBrush(DisplayRectangle, _startColor, _endColor, - LinearGradientMode.Vertical)) - { - e.Graphics.FillRectangle(brush, - new Rectangle(0, 0, _usedBars.Length * BlockSize.Width, BlockSize.Height)); - } - - using (var pen = new Pen(Color.FromArgb(75, 255, 255, 255))) - { - for (var i = 0; i < _usedBars.Length; i++) - { - e.Graphics.DrawLine(pen, (i + 1) * BlockSize.Width, 0, - (i + 1) * BlockSize.Width, BlockSize.Height); - } - - pen.Color = Color.FromArgb(51, 51, 51); - e.Graphics.DrawLine(pen, 0, Height - 1, _usedBars.Length * BlockSize.Width, - Height - 1); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.Designer.cs deleted file mode 100644 index 758d322db..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.Designer.cs +++ /dev/null @@ -1,184 +0,0 @@ -namespace AlphaTab.Samples.WinForms -{ - partial class TrackDetailsControl - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); - this.isMuteCheck = new System.Windows.Forms.CheckBox(); - this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); - this.isSoloCheck = new System.Windows.Forms.CheckBox(); - this.lblName = new System.Windows.Forms.Label(); - this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); - this.volumeTrack = new System.Windows.Forms.TrackBar(); - this.tableLayoutPanel1.SuspendLayout(); - this.tableLayoutPanel4.SuspendLayout(); - this.tableLayoutPanel3.SuspendLayout(); - this.tableLayoutPanel2.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.volumeTrack)).BeginInit(); - this.SuspendLayout(); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 5; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 150F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 3, 0); - this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 2, 0); - this.tableLayoutPanel1.Controls.Add(this.lblName, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 0); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 1; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(549, 39); - this.tableLayoutPanel1.TabIndex = 0; - // - // tableLayoutPanel4 - // - this.tableLayoutPanel4.ColumnCount = 1; - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel4.Controls.Add(this.isMuteCheck, 0, 1); - this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel4.Location = new System.Drawing.Point(383, 3); - this.tableLayoutPanel4.Name = "tableLayoutPanel4"; - this.tableLayoutPanel4.RowCount = 3; - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel4.Size = new System.Drawing.Size(24, 33); - this.tableLayoutPanel4.TabIndex = 3; - // - // isMuteCheck - // - this.isMuteCheck.Dock = System.Windows.Forms.DockStyle.Fill; - this.isMuteCheck.Enabled = false; - this.isMuteCheck.Location = new System.Drawing.Point(3, 7); - this.isMuteCheck.Name = "isMuteCheck"; - this.isMuteCheck.Size = new System.Drawing.Size(104, 19); - this.isMuteCheck.TabIndex = 0; - this.isMuteCheck.UseVisualStyleBackColor = true; - // - // tableLayoutPanel3 - // - this.tableLayoutPanel3.ColumnCount = 1; - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.Controls.Add(this.isSoloCheck, 0, 1); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel3.Location = new System.Drawing.Point(353, 3); - this.tableLayoutPanel3.Name = "tableLayoutPanel3"; - this.tableLayoutPanel3.RowCount = 3; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(24, 33); - this.tableLayoutPanel3.TabIndex = 2; - // - // isSoloCheck - // - this.isSoloCheck.Dock = System.Windows.Forms.DockStyle.Fill; - this.isSoloCheck.Enabled = false; - this.isSoloCheck.Location = new System.Drawing.Point(3, 7); - this.isSoloCheck.Name = "isSoloCheck"; - this.isSoloCheck.Size = new System.Drawing.Size(104, 19); - this.isSoloCheck.TabIndex = 0; - this.isSoloCheck.UseVisualStyleBackColor = true; - // - // lblName - // - this.lblName.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblName.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.lblName.ForeColor = System.Drawing.Color.White; - this.lblName.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.lblName.Location = new System.Drawing.Point(3, 0); - this.lblName.Name = "lblName"; - this.lblName.Size = new System.Drawing.Size(194, 39); - this.lblName.TabIndex = 0; - this.lblName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.lblName.Click += new System.EventHandler(this.lblName_Click); - // - // tableLayoutPanel2 - // - this.tableLayoutPanel2.ColumnCount = 1; - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel2.Controls.Add(this.volumeTrack, 0, 1); - this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel2.Location = new System.Drawing.Point(203, 3); - this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 3; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(144, 33); - this.tableLayoutPanel2.TabIndex = 1; - // - // volumeTrack - // - this.volumeTrack.AutoSize = false; - this.volumeTrack.Dock = System.Windows.Forms.DockStyle.Fill; - this.volumeTrack.Enabled = false; - this.volumeTrack.Location = new System.Drawing.Point(3, 7); - this.volumeTrack.Maximum = 16; - this.volumeTrack.Name = "volumeTrack"; - this.volumeTrack.Size = new System.Drawing.Size(141, 19); - this.volumeTrack.TabIndex = 0; - this.volumeTrack.TickStyle = System.Windows.Forms.TickStyle.None; - // - // TrackDetailsControl - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(94)))), ((int)(((byte)(95))))); - this.Controls.Add(this.tableLayoutPanel1); - this.Name = "TrackDetailsControl"; - this.Size = new System.Drawing.Size(549, 39); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel4.ResumeLayout(false); - this.tableLayoutPanel3.ResumeLayout(false); - this.tableLayoutPanel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.volumeTrack)).EndInit(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private System.Windows.Forms.Label lblName; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; - private System.Windows.Forms.CheckBox isSoloCheck; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; - private System.Windows.Forms.CheckBox isMuteCheck; - private System.Windows.Forms.TrackBar volumeTrack; - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.cs deleted file mode 100644 index 674984286..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Windows.Forms; -using AlphaTab.Model; -using Color = System.Drawing.Color; - -namespace AlphaTab.Samples.WinForms -{ - public partial class TrackDetailsControl : UserControl - { - private bool _isSelected; - private Track _track; - - public bool IsSelected - { - get => _isSelected; - set - { - _isSelected = value; - BackColor = value ? Color.FromArgb(116, 118, 117) : Color.FromArgb(93, 94, 95); - } - } - - public Track Track - { - get => _track; - set - { - _track = value; - TrackName = value.Name; - Volume = (int)value.PlaybackInfo.Volume; - IsSolo = value.PlaybackInfo.IsSolo; - IsMute = value.PlaybackInfo.IsMute; - } - } - - public string TrackName - { - get => lblName.Text; - set => lblName.Text = value; - } - - public int Volume - { - get => volumeTrack.Value; - set => volumeTrack.Value = value; - } - - public bool IsSolo - { - get => isSoloCheck.Checked; - set => isSoloCheck.Checked = value; - } - - public bool IsMute - { - get => isMuteCheck.Checked; - set => isMuteCheck.Checked = value; - } - - public TrackDetailsControl() - { - InitializeComponent(); - } - - public TrackDetailsControl(Track track) - { - InitializeComponent(); - Track = track; - } - - public event EventHandler Selected; - protected virtual void OnSelected() - { - var handler = Selected; - if (handler != null) - { - handler(this, EventArgs.Empty); - } - } - - private void lblName_Click(object sender, EventArgs e) - { - OnSelected(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.resx b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.resx deleted file mode 100644 index 1af7de150..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackDetailsControl.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.Designer.cs deleted file mode 100644 index cf290133e..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.Designer.cs +++ /dev/null @@ -1,132 +0,0 @@ -namespace AlphaTab.Samples.WinForms -{ - partial class TrackHeaderControl - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.lblName = new System.Windows.Forms.Label(); - this.label1 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.label3 = new System.Windows.Forms.Label(); - this.tableLayoutPanel1.SuspendLayout(); - this.SuspendLayout(); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 5; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 150F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.label3, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.lblName, 0, 0); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 1; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(549, 39); - this.tableLayoutPanel1.TabIndex = 0; - // - // lblName - // - this.lblName.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblName.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.lblName.ForeColor = System.Drawing.Color.White; - this.lblName.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.lblName.Location = new System.Drawing.Point(203, 0); - this.lblName.Name = "lblName"; - this.lblName.Size = new System.Drawing.Size(144, 39); - this.lblName.TabIndex = 0; - this.lblName.Text = "Name"; - this.lblName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // label1 - // - this.label1.Dock = System.Windows.Forms.DockStyle.Fill; - this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.ForeColor = System.Drawing.Color.White; - this.label1.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.label1.Location = new System.Drawing.Point(3, 0); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(194, 39); - this.label1.TabIndex = 1; - this.label1.Text = "Vol."; - this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // label2 - // - this.label2.Dock = System.Windows.Forms.DockStyle.Fill; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.ForeColor = System.Drawing.Color.White; - this.label2.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.label2.Location = new System.Drawing.Point(383, 0); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(24, 39); - this.label2.TabIndex = 2; - this.label2.Text = "M"; - this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // label3 - // - this.label3.Dock = System.Windows.Forms.DockStyle.Fill; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.ForeColor = System.Drawing.Color.White; - this.label3.ImageAlign = System.Drawing.ContentAlignment.TopLeft; - this.label3.Location = new System.Drawing.Point(353, 0); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(24, 39); - this.label3.TabIndex = 3; - this.label3.Text = "S"; - this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // - // TrackHeaderControl - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(94)))), ((int)(((byte)(95))))); - this.Controls.Add(this.tableLayoutPanel1); - this.Name = "TrackHeaderControl"; - this.Size = new System.Drawing.Size(549, 39); - this.tableLayoutPanel1.ResumeLayout(false); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private System.Windows.Forms.Label lblName; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label1; - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.cs b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.cs deleted file mode 100644 index ef8ceca8b..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Windows.Forms; - -namespace AlphaTab.Samples.WinForms -{ - public partial class TrackHeaderControl : UserControl - { - public TrackHeaderControl() - { - InitializeComponent(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.resx b/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.resx deleted file mode 100644 index 1af7de150..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.WinForms/TrackHeaderControl.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj b/src.csharp/Samples/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj deleted file mode 100644 index aa70e6e91..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/AlphaTab.Samples.Wpf.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - netcoreapp3.1 - true - WinExe - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml b/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml deleted file mode 100644 index 9aa2eb59f..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml.cs deleted file mode 100644 index 2a75a1c26..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/App.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Globalization; -using System.Threading; -using System.Windows; -using System.Windows.Markup; -using AlphaTab.Samples.Wpf.ViewModel; - -namespace AlphaTab.Samples.Wpf -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App - { - public static void InitializeCultures() - { - Thread.CurrentThread.CurrentCulture = new CultureInfo("en-us"); - Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us"); - - FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata( - XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); - } - - protected override void OnStartup(StartupEventArgs e) - { - base.OnStartup(e); - ViewModelBase.Initialize(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Controls/ToolBarCustom.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Controls/ToolBarCustom.cs deleted file mode 100644 index f38e891c8..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Controls/ToolBarCustom.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace AlphaTab.Samples.Wpf.Controls -{ - /// - /// A custom toolbar with hidden overflow button - /// - public class ToolBarCustom : ToolBar - { - public ToolBarCustom() - { - Loaded += OnLoaded; - } - - private void OnLoaded(object sender, RoutedEventArgs e) - { - var overflowGrid = Template.FindName("OverflowGrid", this) as FrameworkElement; - if (overflowGrid != null) - { - overflowGrid.Visibility = Visibility.Collapsed; - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/BoolToBrushConverter.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/BoolToBrushConverter.cs deleted file mode 100644 index 610a5f975..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/BoolToBrushConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Media; - -namespace AlphaTab.Samples.Wpf.Converter -{ - /// - /// A simple ValueConverter which converts a bool to a associated brush. - /// - public class BoolToBrushConverter : IValueConverter - { - public Brush TrueBrush { get; set; } - public Brush FalseBrush { get; set; } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value is bool && (bool) value ? TrueBrush : FalseBrush; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/PlayerStateToImageSourceConverter.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/PlayerStateToImageSourceConverter.cs deleted file mode 100644 index 0f9b7fb0a..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Converter/PlayerStateToImageSourceConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using System.Windows.Media; -using AlphaTab.Synth; - -namespace AlphaTab.Samples.Wpf.Converter -{ - internal class PlayerStateToImageSourceConverter : IValueConverter - { - public ImageSource PlayImage { get; set; } - public ImageSource PauseImage { get; set; } - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is PlayerState state) - { - switch (state) - { - case PlayerState.Paused: - return PlayImage; - case PlayerState.Playing: - return PauseImage; - default: - throw new ArgumentOutOfRangeException(); - } - } - - return null; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/DialogService.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/DialogService.cs deleted file mode 100644 index 5320b2648..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/DialogService.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Windows; -using AlphaTab.Model; -using AlphaTab.Samples.Wpf.ViewModel; -using Microsoft.Win32; - -namespace AlphaTab.Samples.Wpf.Data -{ - /// - /// This DialogService implementation opens uses WPF dialogs - /// - public class DialogService : IDialogService - { - public string OpenFile() - { - var dialog = new OpenFileDialog - { - Filter = "Supported Files (*.gp3, *.gp4, *.gp5, *.gpx, *.gp)|*.gp3;*.gp4;*.gp5;*.gpx;*.gp" - }; - if (dialog.ShowDialog(Application.Current.MainWindow).GetValueOrDefault()) - { - return dialog.FileName; - } - return null; - } - - public void ShowScoreInfo(Score score) - { - var viewModel = new ScoreInfoViewModel(score); - var window = new ScoreInfoWindow(); - window.DataContext = viewModel; - window.ShowDialog(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/ErrorService.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/ErrorService.cs deleted file mode 100644 index f0fbb6946..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/ErrorService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Windows; -using AlphaTab.Samples.Wpf.ViewModel; - -namespace AlphaTab.Samples.Wpf.Data -{ - /// - /// This error service implementation shows errors as messageboxes on the main window - /// - public class ErrorService : IErrorService - { - public void OpenFailed(Exception e) - { - ViewModelBase.InvokeOnUi(() => - { - MessageBox.Show(Application.Current.MainWindow, e.Message, "An error during opening the file occured", - MessageBoxButton.OK, MessageBoxImage.Error); - }); - } - } -} \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IDialogService.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IDialogService.cs deleted file mode 100644 index 98b1a9ca3..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IDialogService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using AlphaTab.Model; - -namespace AlphaTab.Samples.Wpf.Data -{ - public interface IDialogService - { - /// - /// Called when the application wants to open a new file. - /// Implementation should ask the user to select a file from the filesystem. - /// - /// The path to the file which should be opened or null if no file should be opened - string OpenFile(); - - /// - /// Called when the application wants to show a score information. - /// - void ShowScoreInfo(Score score); - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IErrorService.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IErrorService.cs deleted file mode 100644 index 4dfe10bab..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Data/IErrorService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace AlphaTab.Samples.Wpf.Data -{ - /// - /// Implement this interface to handle application errors. - /// - public interface IErrorService - { - /// - /// Called when an error during opening a file occurs. - /// - /// The exception occured during opening the file - void OpenFailed(Exception e); - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_pause.png b/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_pause.png deleted file mode 100644 index 186f361f0..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_pause.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_play.png b/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_play.png deleted file mode 100644 index 3b64790b9..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/control_play.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/folder_page_white.png b/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/folder_page_white.png deleted file mode 100644 index b20277a8f..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/folder_page_white.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/information.png b/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/information.png deleted file mode 100644 index 93c67f2bf..000000000 Binary files a/src.csharp/Samples/AlphaTab.Samples.Wpf/Images/32/information.png and /dev/null differ diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml b/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml deleted file mode 100644 index ea7d8d4fa..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml.cs deleted file mode 100644 index c3371659e..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/MainWindow.xaml.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Windows; -using AlphaTab.Samples.Wpf.Data; -using AlphaTab.Samples.Wpf.ViewModel; - -namespace AlphaTab.Samples.Wpf -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow - { - public MainWindow() - { - InitializeComponent(); - - // ensure the UI is using en-us as culture - // we need this culture for correct WPF path string generation - // in a German culture it could happen that we have a , as a decimal separator. - App.InitializeCultures(); - - // create a our viewmodel for databinding - var viewModel = new MainViewModel(new DialogService(), new ErrorService()); - DataContext = viewModel; - } - - private void OnPlayPauseClick(object sender, RoutedEventArgs e) - { - TablatureControl.Api.PlayPause(); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.Designer.cs deleted file mode 100644 index 2c995dcdb..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace AlphaTab.Samples.Wpf.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AlphaTab.Samples.Wpf.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.resx b/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.resx deleted file mode 100644 index af7dbebba..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.Designer.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.Designer.cs deleted file mode 100644 index 3de8d93d9..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace AlphaTab.Samples.Wpf.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.settings b/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.settings deleted file mode 100644 index 033d7a5e9..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Readme.md b/src.csharp/Samples/AlphaTab.Samples.Wpf/Readme.md deleted file mode 100644 index 8ab36af63..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# AlphaTab WPF Sample - -This sample uses GDI+ or SkiaSharp (user choice) as drawing engine and uses the WPF Control to actually display the rendered image. \ No newline at end of file diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml b/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml deleted file mode 100644 index 58e20d3f8..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml.cs deleted file mode 100644 index 2abd95f45..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ScoreInfoWindow.xaml.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Windows; -using System.Windows.Input; - -namespace AlphaTab.Samples.Wpf -{ - /// - /// Interaction logic for ScoreInfoWindow.xaml - /// - public partial class ScoreInfoWindow - { - public ScoreInfoWindow() - { - InitializeComponent(); - } - - private void OnOkClick(object sender, RoutedEventArgs e) - { - DialogResult = true; - } - - protected override void OnPreviewKeyDown(KeyEventArgs e) - { - base.OnPreviewKeyDown(e); - if (e.Key == Key.Escape) - { - DialogResult = false; - e.Handled = true; - } - } - - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/Utils/RelayCommand.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/Utils/RelayCommand.cs deleted file mode 100644 index 4fce26ab0..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/Utils/RelayCommand.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Windows.Input; -using AlphaTab.Samples.Wpf.ViewModel; - -namespace AlphaTab.Samples.Wpf.Utils -{ - /// - /// This command implementation delegates the execution to a referenced method. - /// - public class RelayCommand : ICommand - { - private readonly Action _action; - private readonly Func _canExecute; - - public RelayCommand(Action action, Func canExecute = null) - { - _action = action; - _canExecute = canExecute; - } - - public bool CanExecute(object parameter) - { - return _canExecute == null || _canExecute(); - } - - public void Execute(object parameter) - { - _action(); - } - - public event EventHandler CanExecuteChanged; - public virtual void RaiseCanExecuteChanged() - { - var handler = CanExecuteChanged; - if (handler != null) - { - ViewModelBase.InvokeOnUi(() => - { - handler(this, EventArgs.Empty); - }); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/MainViewModel.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/MainViewModel.cs deleted file mode 100644 index 0a31121c8..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/MainViewModel.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Input; -using AlphaTab.Importer; -using AlphaTab.Model; -using AlphaTab.Samples.Wpf.Data; -using AlphaTab.Samples.Wpf.Utils; - -namespace AlphaTab.Samples.Wpf.ViewModel -{ - /// - /// This viewmodel contains the data and logic for the main application window. - /// - public class MainViewModel : ViewModelBase - { - // references to the services we want to use - private readonly IDialogService _dialogService; - private readonly IErrorService _errorService; - - #region Score Data - - // those properties store the score information - - private Score _score; - private int _currentTrackIndex; - private IEnumerable _trackInfos; - private TrackViewModel _selectedTrackInfo; - private readonly RelayCommand _showScoreInfoCommand; - - /// - /// A command which raises the method - /// - public ICommand ShowScoreInfoCommand => _showScoreInfoCommand; - - /// - /// Gets or sets the currently opened score. - /// If a new score is selected, the first track gets loaded. - /// - public Score Score - { - get => _score; - set - { - _score = value; - OnPropertyChanged(); - OnPropertyChanged("ScoreTitle"); - _showScoreInfoCommand.RaiseCanExecuteChanged(); - - // select the first track - CurrentTrackIndex = 0; - } - } - - /// - /// Gets or sets the title of the currently loaded sore. - /// - public string ScoreTitle => _score == null ? "No File Opened" : _score.Title; - - /// - /// Gets or sets the index of the track which should be currently displayed. - /// - public int CurrentTrackIndex - { - get => _currentTrackIndex; - set - { - _currentTrackIndex = value; - - // update the visual track selection if a new track is selected - UpdateSelectedViewModel(); - - // notify the ui - OnPropertyChanged(); - OnPropertyChanged(nameof(CurrentTracks)); - } - } - - /// - /// Gets the currently selected track. - /// - public IEnumerable CurrentTracks - { - get - { - if (Score == null || CurrentTrackIndex < 0 || CurrentTrackIndex >= _score.Tracks.Count) - { - return null; - } - - return new[] { _score.Tracks[_currentTrackIndex] }; - } - } - - /// - /// Gets the information about the currently loaded tracks - /// - public IEnumerable TrackInfos - { - get => _trackInfos; - private set - { - _trackInfos = value; - - // ensure correct selection - UpdateSelectedViewModel(); - OnPropertyChanged(); - } - } - - /// - /// Gets or sets the currently selected track. - /// - public TrackViewModel SelectedTrackInfo - { - get => _selectedTrackInfo; - set - { - _selectedTrackInfo = value; - // select the new track - if (_score != null) - { - CurrentTrackIndex = _score.Tracks.IndexOf(_selectedTrackInfo.Track); - } - OnPropertyChanged(); - } - } - - /// - /// Opens a score info dialog for the current score. - /// - public void ShowScoreInfo() - { - if (_score != null) - { - _dialogService.ShowScoreInfo(_score); - } - } - - - - #endregion - - #region Score Loading - - /// - /// A command which raises a file opening - /// - public ICommand OpenFileCommand { get; private set; } - - /// - /// Opens a new file by loading the file path using the IO service. - /// - public void OpenFile() - { - OpenFile(_dialogService.OpenFile()); - } - - /// - /// Opens a new file from the specified file path. - /// - /// the path to the file to load - private void OpenFile(string file) - { - if (!string.IsNullOrWhiteSpace(file) && File.Exists(file)) - { - InternalOpenFile(file); - } - } - - private void InternalOpenFile(string file) - { - Task.Factory.StartNew(() => - { - try - { - // load the score from the filesystem - Score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(file)); - - // build the track info objects for the ui - var trackInfos = new TrackViewModel[(int)Score.Tracks.Count]; - for (var i = 0; i < trackInfos.Length; i++) - { - trackInfos[i] = new TrackViewModel(Score.Tracks[i]); - } - TrackInfos = trackInfos; - } - catch (Exception e) - { - _errorService.OpenFailed(e); - } - }); - } - - /// - /// Updates the currently selected viewmodel - /// - private void UpdateSelectedViewModel() - { - if (_trackInfos != null) - { - var currentTrackLookup = CurrentTracks.ToLookup(t => t.Index); - foreach (var trackViewModel in _trackInfos) - { - trackViewModel.IsSelected = currentTrackLookup.Contains(trackViewModel.Track.Index); - } - } - } - - #endregion - - public MainViewModel(IDialogService dialogService, IErrorService errorService) - { - _dialogService = dialogService; - _errorService = errorService; - OpenFileCommand = new RelayCommand(OpenFile); - _showScoreInfoCommand = new RelayCommand(ShowScoreInfo, () => _score != null); - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ScoreInfoViewModel.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ScoreInfoViewModel.cs deleted file mode 100644 index 9dd8211e8..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ScoreInfoViewModel.cs +++ /dev/null @@ -1,132 +0,0 @@ -using AlphaTab.Model; - -namespace AlphaTab.Samples.Wpf.ViewModel -{ - public class ScoreInfoViewModel : ViewModelBase - { - private string _tab; - private string _words; - private string _title; - private string _subTitle; - private string _notices; - private string _music; - private string _instructions; - private string _copyright; - private string _artist; - private string _album; - - public ScoreInfoViewModel(Score score) - { - _tab = score.Tab; - _words = score.Words; - _title = score.Title; - _subTitle = score.SubTitle; - _notices = score.Notices; - _music = score.Music; - _instructions = score.Instructions; - _copyright = score.Copyright; - _artist = score.Artist; - _album = score.Album; - } - - public string Album - { - get => _album; - set - { - _album = value; - OnPropertyChanged(); - } - } - - public string Artist - { - get => _artist; - set - { - _artist = value; - OnPropertyChanged(); - } - } - - public string Copyright - { - get => _copyright; - set - { - _copyright = value; - OnPropertyChanged(); - } - } - - public string Instructions - { - get => _instructions; - set - { - _instructions = value; - OnPropertyChanged(); - } - } - - public string Music - { - get => _music; - set - { - _music = value; - OnPropertyChanged(); - } - } - - public string Notices - { - get => _notices; - set - { - _notices = value; - OnPropertyChanged(); - } - } - - public string SubTitle - { - get => _subTitle; - set - { - _subTitle = value; - OnPropertyChanged(); - } - } - - public string Title - { - get => _title; - set - { - _title = value; - OnPropertyChanged(); - } - } - - public string Words - { - get => _words; - set - { - _words = value; - OnPropertyChanged(); - } - } - - public string Tab - { - get => _tab; - set - { - _tab = value; - OnPropertyChanged(); - } - } - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/TrackViewModel.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/TrackViewModel.cs deleted file mode 100644 index 166b5fec6..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/TrackViewModel.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System.Linq; -using AlphaTab.Model; - -namespace AlphaTab.Samples.Wpf.ViewModel -{ - /// - /// A viewmodel for displaying track information in the UI - /// - public class TrackViewModel : ViewModelBase - { - private TrackType _trackType; - private bool[] _usedBars; - private bool _isSelected; - private Track _track; - - public bool IsSelected - { - get => _isSelected; - set - { - _isSelected = value; - OnPropertyChanged(); - } - } - - public TrackType TrackType - { - get => _trackType; - set - { - _trackType = value; - OnPropertyChanged(); - } - } - - public string Name - { - get => _track.Name; - set - { - _track.Name = value; - OnPropertyChanged(); - } - } - - public int Volume - { - get => (int)_track.PlaybackInfo.Volume; - set - { - _track.PlaybackInfo.Volume = value; - OnPropertyChanged(); - } - } - - public bool IsSolo - { - get => _track.PlaybackInfo.IsSolo; - set - { - _track.PlaybackInfo.IsSolo = value; - OnPropertyChanged(); - } - } - - public bool IsMute - { - get => _track.PlaybackInfo.IsMute; - set - { - _track.PlaybackInfo.IsMute = value; - OnPropertyChanged(); - } - } - - public bool[] UsedBars - { - get => _usedBars; - set - { - _usedBars = value; - OnPropertyChanged(); - } - } - - public Track Track - { - get => _track; - set - { - _track = value; - OnPropertyChanged(); - } - } - - public TrackViewModel(Track track) - { - _track = track; - - // general midi Programs - if (track.Staves.Any(s=>s.IsPercussion)) - { - TrackType = TrackType.Drums; - } - else if (track.PlaybackInfo.Program >= 0 && track.PlaybackInfo.Program <= 6) - { - TrackType = TrackType.Piano; - } - else if (track.PlaybackInfo.Program >= 26 && track.PlaybackInfo.Program <= 31) - { - TrackType = TrackType.ElectricGuitar; - } - else if (track.PlaybackInfo.Program >= 32 && track.PlaybackInfo.Program <= 39) - { - TrackType = TrackType.BassGuitar; - } - else - { - TrackType = TrackType.Default; - } - - // scan all bars if they have any note - _usedBars = new bool[(int)track.Score.MasterBars.Count]; - for (var s = 0; s < track.Staves.Count; s++) - { - var staff = track.Staves[s]; - for (var barI = 0; barI < staff.Bars.Count; barI++) - { - var bar = staff.Bars[barI]; - _usedBars[barI] = false; - - for (var voiceI = 0; voiceI < bar.Voices.Count && (!_usedBars[barI]); voiceI++) - { - var voice = bar.Voices[voiceI]; - for (var i = 0; i < voice.Beats.Count; i++) - { - var b = voice.Beats[i]; - if (!b.IsRest) - { - _usedBars[barI] = true; - } - } - } - } - } - } - } - - public enum TrackType - { - Default, - ElectricGuitar, - BassGuitar, - Drums, - Piano - } -} diff --git a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ViewModelBase.cs b/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ViewModelBase.cs deleted file mode 100644 index 6c5201298..000000000 --- a/src.csharp/Samples/AlphaTab.Samples.Wpf/ViewModel/ViewModelBase.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using System.Windows.Threading; -using JetBrains.Annotations; - -namespace AlphaTab.Samples.Wpf.ViewModel -{ - public class ViewModelBase : INotifyPropertyChanged - { - public static Dispatcher UiDispatcher { get; private set; } - - public static void Initialize() - { - UiDispatcher = Dispatcher.CurrentDispatcher; - } - - public static void InvokeOnUi(Action action) - { - if (UiDispatcher.CheckAccess()) - { - action(); - } - else - { - UiDispatcher.BeginInvoke(action); - } - } - - public event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - var handler = PropertyChanged; - if (handler != null) - { - InvokeOnUi(() => - { - handler(this, new PropertyChangedEventArgs(propertyName)); - }); - } - } - } -} diff --git a/src/AlphaTabApiBase.ts b/src/AlphaTabApiBase.ts index 1af18fddd..31eca2b22 100644 --- a/src/AlphaTabApiBase.ts +++ b/src/AlphaTabApiBase.ts @@ -13,7 +13,6 @@ import { EventEmitter, IEventEmitter, IEventEmitterOfT, EventEmitterOfT } from ' import { AlphaTexImporter } from '@src/importer/AlphaTexImporter'; -import { ByteBuffer } from '@src/io/ByteBuffer'; import { Beat } from '@src/model/Beat'; import { Score } from '@src/model/Score'; import { Track } from '@src/model/Track'; @@ -40,9 +39,11 @@ import { Settings } from '@src/Settings'; import { Logger } from '@src/Logger'; import { ModelUtils } from '@src/model/ModelUtils'; import { AlphaTabError, AlphaTabErrorType } from '@src/AlphaTabError'; -import { Note } from './model/Note'; -import { MidiEventType } from './midi/MidiEvent'; -import { MidiEventsPlayedEventArgs } from './synth/MidiEventsPlayedEventArgs'; +import { Note } from '@src/model/Note'; +import { MidiEventType } from '@src/midi/MidiEvent'; +import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; +import { ActiveBeatsChangedEventArgs } from '@src/synth/ActiveBeatsChangedEventArgs'; class SelectionInfo { public beat: Beat; @@ -62,6 +63,7 @@ class SelectionInfo { export class AlphaTabApiBase { private _startTime: number = 0; private _trackIndexes: number[] | null = null; + private _isDestroyed: boolean = false; /** * Gets the UI facade to use for interacting with the user interface. */ @@ -111,23 +113,26 @@ export class AlphaTabApiBase { this.canvasElement = uiFacade.createCanvasElement(); this.container.appendChild(this.canvasElement); - this.container.resize.on( - Environment.throttle(() => { - if (this.container.width !== this.renderer.width) { - this.triggerResize(); - } - }, uiFacade.resizeThrottle) - ); if ( this.settings.core.useWorkers && this.uiFacade.areWorkersSupported && - Environment.getRenderEngineFactory(this.settings).supportsWorkers + Environment.getRenderEngineFactory(this.settings.core.engine).supportsWorkers ) { this.renderer = this.uiFacade.createWorkerRenderer(); } else { this.renderer = new ScoreRenderer(this.settings); } + this.container.resize.on( + Environment.throttle(() => { + if (this._isDestroyed) { + return; + } + if (this.container.width !== this.renderer.width) { + this.triggerResize(); + } + }, uiFacade.resizeThrottle) + ); let initialResizeEventInfo: ResizeEventArgs = new ResizeEventArgs(); initialResizeEventInfo.oldWidth = this.renderer.width; initialResizeEventInfo.newWidth = this.container.width | 0; @@ -145,7 +150,8 @@ export class AlphaTabApiBase { this.renderer.preRender.on(_ => { this._startTime = Date.now(); }); - this.renderer.partialRenderFinished.on(this.appendRenderResult.bind(this)); + this.renderer.partialLayoutFinished.on(this.appendRenderResult.bind(this)); + this.renderer.partialRenderFinished.on(this.updateRenderResult.bind(this)); this.renderer.renderFinished.on(r => { this.appendRenderResult(r); this.appendRenderResult(null); // marks last element @@ -165,6 +171,7 @@ export class AlphaTabApiBase { * Destroys the alphaTab control and restores the initial state of the UI. */ public destroy(): void { + this._isDestroyed = true; if (this.player) { this.player.destroy(); } @@ -176,6 +183,10 @@ export class AlphaTabApiBase { * Applies any changes that were done to the settings object and informs the {@link renderer} about any new values to consider. */ public updateSettings(): void { + const score = this.score; + if (score) { + ModelUtils.applyPitchOffsets(this.settings, score); + } this.renderer.updateSettings(this.settings); // enable/disable player if needed if (this.settings.player.enablePlayer) { @@ -183,6 +194,7 @@ export class AlphaTabApiBase { } else { this.destroyPlayer(); } + this.onSettingsUpdated(); } /** @@ -204,7 +216,7 @@ export class AlphaTabApiBase { } ); } catch (e) { - this.onError(e); + this.onError(e as Error); return false; } } @@ -264,8 +276,8 @@ export class AlphaTabApiBase { } private internalRenderTracks(score: Score, tracks: Track[]): void { + ModelUtils.applyPitchOffsets(this.settings, score); if (score !== this.score) { - ModelUtils.applyPitchOffsets(this.settings, score); this.score = score; this.tracks = tracks; this._trackIndexes = []; @@ -285,6 +297,9 @@ export class AlphaTabApiBase { } } + /** + * @internal + */ private triggerResize(): void { if (!this.container.isVisible) { Logger.warning( @@ -317,8 +332,12 @@ export class AlphaTabApiBase { this._cursorWrapper.height = result.totalHeight; } } - if (!result || result.renderResult) { - this.uiFacade.beginAppendRenderResults(result); + this.uiFacade.beginAppendRenderResults(result); + } + + private updateRenderResult(result: RenderFinishedEventArgs | null): void { + if (result && result.renderResult) { + this.uiFacade.beginUpdateRenderResults(result); } } @@ -330,12 +349,12 @@ export class AlphaTabApiBase { public tex(tex: string, tracks?: number[]): void { try { let parser: AlphaTexImporter = new AlphaTexImporter(); - let data: ByteBuffer = ByteBuffer.fromString(tex); - parser.init(data, this.settings); + parser.logErrors = true; + parser.initFromString(tex, this.settings); let score: Score = parser.readScore(); this.renderScore(score, tracks); } catch (e) { - this.onError(e); + this.onError(e as Error); } } @@ -372,13 +391,21 @@ export class AlphaTabApiBase { if (this.uiFacade.canRender) { // when font is finally loaded, start rendering this.renderer.width = this.container.width; - this.renderer.renderScore(this.score!, this._trackIndexes as any); + this.renderer.renderScore(this.score, this._trackIndexes); } else { this.uiFacade.canRenderChanged.on(() => this.render()); } } private _tickCache: MidiTickLookup | null = null; + + /** + * Gets the tick cache related to the current score. + */ + public get tickCache(): MidiTickLookup | null { + return this._tickCache; + } + /** * Gets the alphaSynth player used for playback. This is the low-level API to the Midi synthesizer used for playback. */ @@ -524,10 +551,13 @@ export class AlphaTabApiBase { } this.player.destroy(); this.player = null; + this._previousTick = 0; + this._playerState = PlayerState.Paused; this.destroyCursors(); } private setupPlayer(): void { + this.updateCursors(); if (this.player) { return; } @@ -559,12 +589,9 @@ export class AlphaTabApiBase { this.player.stateChanged.on(this.onPlayerStateChanged.bind(this)); this.player.positionChanged.on(this.onPlayerPositionChanged.bind(this)); this.player.midiEventsPlayed.on(this.onMidiEventsPlayed.bind(this)); + this.player.playbackRangeChanged.on(this.onPlaybackRangeChanged.bind(this)); this.player.finished.on(this.onPlayerFinished.bind(this)); - if (this.settings.player.enableCursor) { - this.setupCursors(); - } else { - this.destroyCursors(); - } + this.setupPlayerEvents(); } private loadMidiForScore(): void { @@ -680,7 +707,11 @@ export class AlphaTabApiBase { // we generate a new midi file containing only the beat let midiFile: MidiFile = new MidiFile(); let handler: AlphaSynthMidiFileHandler = new AlphaSynthMidiFileHandler(midiFile); - let generator: MidiFileGenerator = new MidiFileGenerator(beat.voice.bar.staff.track.score, this.settings, handler); + let generator: MidiFileGenerator = new MidiFileGenerator( + beat.voice.bar.staff.track.score, + this.settings, + handler + ); generator.generateSingleBeat(beat); this.player.playOneTimeMidiFile(midiFile); @@ -698,20 +729,24 @@ export class AlphaTabApiBase { // we generate a new midi file containing only the beat let midiFile: MidiFile = new MidiFile(); let handler: AlphaSynthMidiFileHandler = new AlphaSynthMidiFileHandler(midiFile); - let generator: MidiFileGenerator = new MidiFileGenerator(note.beat.voice.bar.staff.track.score, this.settings, handler); + let generator: MidiFileGenerator = new MidiFileGenerator( + note.beat.voice.bar.staff.track.score, + this.settings, + handler + ); generator.generateSingleNote(note); this.player.playOneTimeMidiFile(midiFile); } - private _cursorWrapper: IContainer | null = null; private _barCursor: IContainer | null = null; private _beatCursor: IContainer | null = null; private _selectionWrapper: IContainer | null = null; private _previousTick: number = 0; private _playerState: PlayerState = PlayerState.Paused; - private _currentBeat: Beat | null = null; + private _currentBeat: MidiTickLookupFindBeatResult | null = null; + private _currentBarBounds: MasterBarBounds | null = null; private _previousStateForCursor: PlayerState = PlayerState.Paused; private _previousCursorCache: BoundsLookup | null = null; private _lastScroll: number = 0; @@ -725,29 +760,37 @@ export class AlphaTabApiBase { this._barCursor = null; this._beatCursor = null; this._selectionWrapper = null; - this._previousTick = 0; - this._playerState = PlayerState.Paused; } - private setupCursors(): void { - // - // Create cursors - let cursors = this.uiFacade.createCursors(); - if (!cursors) { - return; + private updateCursors() { + if (this.settings.player.enableCursor && !this._cursorWrapper) { + // + // Create cursors + let cursors = this.uiFacade.createCursors(); + if (cursors) { + // store options and created elements for fast access + this._cursorWrapper = cursors.cursorWrapper; + this._barCursor = cursors.barCursor; + this._beatCursor = cursors.beatCursor; + this._selectionWrapper = cursors.selectionWrapper; + } + if (this._currentBeat !== null) { + this.cursorUpdateBeat(this._currentBeat!, false, this._previousTick > 10, true); + } + } else if (!this.settings.player.enableCursor && this._cursorWrapper) { + this.destroyCursors(); } - // store options and created elements for fast access - this._cursorWrapper = cursors.cursorWrapper; - this._barCursor = cursors.barCursor; - this._beatCursor = cursors.beatCursor; - this._selectionWrapper = cursors.selectionWrapper; + } + + private setupPlayerEvents(): void { // // Hook into events this._previousTick = 0; this._playerState = PlayerState.Paused; // we need to update our position caches if we render a tablature this.renderer.postRenderFinished.on(() => { - this.cursorUpdateTick(this._previousTick, false); + this._currentBeat = null; + this.cursorUpdateTick(this._previousTick, false, this._previousTick > 10); }); if (this.player) { this.player.positionChanged.on(e => { @@ -759,11 +802,12 @@ export class AlphaTabApiBase { this.player.stateChanged.on(e => { this._playerState = e.state; if (!e.stopped && e.state === PlayerState.Paused) { - let currentBeat: Beat | null = this._currentBeat; - let tickCache: MidiTickLookup | null = this._tickCache; + let currentBeat = this._currentBeat; + let tickCache = this._tickCache; if (currentBeat && tickCache) { this.player!.tickPosition = - tickCache.getMasterBarStart(currentBeat.voice.bar.masterBar) + currentBeat.playbackStart; + tickCache.getMasterBarStart(currentBeat.currentBeat.voice.bar.masterBar) + + currentBeat.currentBeat.playbackStart; } } }); @@ -774,38 +818,35 @@ export class AlphaTabApiBase { * updates the cursors to highlight the beat at the specified tick position * @param tick * @param stop + * @param shouldScroll whether we should scroll to the bar (if scrolling is active) */ - private cursorUpdateTick(tick: number, stop: boolean = false): void { - this.uiFacade.beginInvoke(() => { - let cache: MidiTickLookup | null = this._tickCache; - if (cache) { - let tracks: Track[] = this.tracks; - if (tracks.length > 0) { - let beat: MidiTickLookupFindBeatResult | null = cache.findBeat(tracks, tick); - if (beat) { - this.cursorUpdateBeat( - beat.currentBeat, - beat.nextBeat, - beat.duration, - stop, - beat.beatsToHighlight - ); - } + private cursorUpdateTick(tick: number, stop: boolean, shouldScroll: boolean = false): void { + let cache: MidiTickLookup | null = this._tickCache; + if (cache) { + let tracks: Track[] = this.tracks; + if (tracks.length > 0) { + let beat: MidiTickLookupFindBeatResult | null = cache.findBeat(tracks, tick, this._currentBeat); + if (beat) { + this.cursorUpdateBeat(beat, stop, shouldScroll); } } - }); + } } /** * updates the cursors to highlight the specified beat */ private cursorUpdateBeat( - beat: Beat, - nextBeat: Beat | null, - duration: number, + lookupResult: MidiTickLookupFindBeatResult, stop: boolean, - beatsToHighlight: Beat[] | null = null + shouldScroll: boolean, + forceUpdate: boolean = false ): void { + const beat: Beat = lookupResult.currentBeat; + const nextBeat: Beat | null = lookupResult.nextBeat; + const duration: number = lookupResult.duration; + const beatsToHighlight = lookupResult.beatsToHighlight; + if (!beat) { return; } @@ -813,56 +854,168 @@ export class AlphaTabApiBase { if (!cache) { return; } - let previousBeat: Beat | null = this._currentBeat; + let previousBeat = this._currentBeat; let previousCache: BoundsLookup | null = this._previousCursorCache; let previousState: PlayerState | null = this._previousStateForCursor; - this._currentBeat = beat; - this._previousCursorCache = cache; - this._previousStateForCursor = this._playerState; - if (beat === previousBeat && cache === previousCache && previousState === this._playerState) { + if ( + !forceUpdate && + beat === previousBeat?.currentBeat && + cache === previousCache && + previousState === this._playerState + ) { return; } - let barCursor: IContainer | null = this._barCursor; - let beatCursor: IContainer | null = this._beatCursor; let beatBoundings: BeatBounds | null = cache.findBeat(beat); if (!beatBoundings) { return; } + + // only if we really found some bounds we remember the beat and cache we used to + // actually show the cursor + this._currentBeat = lookupResult; + this._previousCursorCache = cache; + this._previousStateForCursor = this._playerState; + + this.uiFacade.beginInvoke(() => { + this.internalCursorUpdateBeat( + beat, + nextBeat, + duration, + stop, + beatsToHighlight, + cache!, + beatBoundings!, + shouldScroll + ); + }); + } + + /** + * Initiates a scroll to the cursor + */ + public scrollToCursor() { + const barBounds = this._currentBarBounds; + if (barBounds) { + this.internalScrollToCursor(barBounds); + } + } + + public internalScrollToCursor(barBoundings: MasterBarBounds) { + let scrollElement: IContainer = this.uiFacade.getScrollContainer(); + let isVertical: boolean = Environment.getLayoutEngineFactory(this.settings.display.layoutMode).vertical; + let mode: ScrollMode = this.settings.player.scrollMode; + if (isVertical) { + // when scrolling on the y-axis, we preliminary check if the new beat/bar have + // moved on the y-axis + let y: number = barBoundings.realBounds.y + this.settings.player.scrollOffsetY; + if (y !== this._lastScroll) { + this._lastScroll = y; + switch (mode) { + case ScrollMode.Continuous: + let elementOffset: Bounds = this.uiFacade.getOffset(scrollElement, this.container); + this.uiFacade.scrollToY(scrollElement, elementOffset.y + y, this.settings.player.scrollSpeed); + break; + case ScrollMode.OffScreen: + let elementBottom: number = + scrollElement.scrollTop + this.uiFacade.getOffset(null, scrollElement).h; + if ( + barBoundings.visualBounds.y + barBoundings.visualBounds.h >= elementBottom || + barBoundings.visualBounds.y < scrollElement.scrollTop + ) { + let scrollTop: number = barBoundings.realBounds.y + this.settings.player.scrollOffsetY; + this.uiFacade.scrollToY(scrollElement, scrollTop, this.settings.player.scrollSpeed); + } + break; + } + } + } else { + // when scrolling on the x-axis, we preliminary check if the new bar has + // moved on the x-axis + let x: number = barBoundings.visualBounds.x; + if (x !== this._lastScroll) { + this._lastScroll = x; + switch (mode) { + case ScrollMode.Continuous: + let scrollLeftContinuous: number = + barBoundings.realBounds.x + this.settings.player.scrollOffsetX; + this._lastScroll = barBoundings.visualBounds.x; + this.uiFacade.scrollToX(scrollElement, scrollLeftContinuous, this.settings.player.scrollSpeed); + break; + case ScrollMode.OffScreen: + let elementRight: number = + scrollElement.scrollLeft + this.uiFacade.getOffset(null, scrollElement).w; + if ( + barBoundings.visualBounds.x + barBoundings.visualBounds.w >= elementRight || + barBoundings.visualBounds.x < scrollElement.scrollLeft + ) { + let scrollLeftOffScreen: number = + barBoundings.realBounds.x + this.settings.player.scrollOffsetX; + this._lastScroll = barBoundings.visualBounds.x; + this.uiFacade.scrollToX( + scrollElement, + scrollLeftOffScreen, + this.settings.player.scrollSpeed + ); + } + break; + } + } + } + } + + private internalCursorUpdateBeat( + beat: Beat, + nextBeat: Beat | null, + duration: number, + stop: boolean, + beatsToHighlight: Beat[], + cache: BoundsLookup, + beatBoundings: BeatBounds, + shouldScroll: boolean + ) { + const barCursor = this._barCursor; + const beatCursor = this._beatCursor; + let barBoundings: MasterBarBounds = beatBoundings.barBounds.masterBarBounds; let barBounds: Bounds = barBoundings.visualBounds; + + this._currentBarBounds = barBoundings; + if (barCursor) { - barCursor.top = barBounds.y; - barCursor.left = barBounds.x; - barCursor.width = barBounds.w; - barCursor.height = barBounds.h; + barCursor.setBounds(barBounds.x, barBounds.y, barBounds.w, barBounds.h); } if (beatCursor) { // move beat to start position immediately - beatCursor.stopAnimation(); - beatCursor.top = barBounds.y; - beatCursor.left = beatBoundings.visualBounds.x; - beatCursor.height = barBounds.h; + if (this.settings.player.enableAnimatedBeatCursor) { + beatCursor.stopAnimation(); + } + beatCursor.setBounds(beatBoundings.visualBounds.x, barBounds.y, 1, barBounds.h); } // if playing, animate the cursor to the next beat - this.uiFacade.removeHighlights(); - if (this._playerState === PlayerState.Playing || stop) { - duration /= this.playbackSpeed; - if (!stop) { - if (beatsToHighlight) { - for (let highlight of beatsToHighlight) { - let className: string = BeatContainerGlyph.getGroupId(highlight); - this.uiFacade.highlightElements(className); - } + if (this.settings.player.enableElementHighlighting) { + this.uiFacade.removeHighlights(); + } + + // actively playing? -> animate cursor and highlight items + let shouldNotifyBeatChange = false; + if (this._playerState === PlayerState.Playing && !stop) { + if (this.settings.player.enableElementHighlighting) { + for (let highlight of beatsToHighlight) { + let className: string = BeatContainerGlyph.getGroupId(highlight); + this.uiFacade.highlightElements(className, beat.voice.bar.index); } + } + + if (this.settings.player.enableAnimatedBeatCursor) { let nextBeatX: number = barBoundings.visualBounds.x + barBoundings.visualBounds.w; // get position of next beat on same stavegroup if (nextBeat) { // if we are moving within the same bar or to the next bar // transition to the next beat, otherwise transition to the end of the bar. if ( - nextBeat.voice.bar.index === beat.voice.bar.index || + (nextBeat.voice.bar.index === beat.voice.bar.index && nextBeat.index > beat.index) || nextBeat.voice.bar.index === beat.voice.bar.index + 1 ) { let nextBeatBoundings: BeatBounds | null = cache.findBeat(nextBeat); @@ -876,80 +1029,51 @@ export class AlphaTabApiBase { } } - if (beatCursor) { - this.uiFacade.beginInvoke(() => { - // Logger.Info("Player", - // "Transition from " + beatBoundings.VisualBounds.X + " to " + nextBeatX + " in " + duration + - // "(" + Player.PlaybackRange + ")"); - beatCursor!.transitionToX(duration, nextBeatX); - }); - } - } - if (!this._beatMouseDown && this.settings.player.scrollMode !== ScrollMode.Off) { - let scrollElement: IContainer = this.uiFacade.getScrollContainer(); - let isVertical: boolean = Environment.getLayoutEngineFactory(this.settings).vertical; - let mode: ScrollMode = this.settings.player.scrollMode; - let elementOffset: Bounds = this.uiFacade.getOffset(scrollElement, this.container); - if (isVertical) { - switch (mode) { - case ScrollMode.Continuous: - let y: number = - elementOffset.y + barBoundings.realBounds.y + this.settings.player.scrollOffsetY; - if (y !== this._lastScroll) { - this._lastScroll = y; - this.uiFacade.scrollToY(scrollElement, y, this.settings.player.scrollSpeed); - } - break; - case ScrollMode.OffScreen: - let elementBottom: number = - scrollElement.scrollTop + this.uiFacade.getOffset(null, scrollElement).h; - if ( - barBoundings.visualBounds.y + barBoundings.visualBounds.h >= elementBottom || - barBoundings.visualBounds.y < scrollElement.scrollTop - ) { - let scrollTop: number = barBoundings.realBounds.y + this.settings.player.scrollOffsetY; - this._lastScroll = barBoundings.visualBounds.x; - this.uiFacade.scrollToY(scrollElement, scrollTop, this.settings.player.scrollSpeed); - } - break; - } - } else { - switch (mode) { - case ScrollMode.Continuous: - let x: number = barBoundings.visualBounds.x; - if (x !== this._lastScroll) { - let scrollLeft: number = barBoundings.realBounds.x + this.settings.player.scrollOffsetX; - this._lastScroll = barBoundings.visualBounds.x; - this.uiFacade.scrollToX(scrollElement, scrollLeft, this.settings.player.scrollSpeed); - } - break; - case ScrollMode.OffScreen: - let elementRight: number = - scrollElement.scrollLeft + this.uiFacade.getOffset(null, scrollElement).w; - if ( - barBoundings.visualBounds.x + barBoundings.visualBounds.w >= elementRight || - barBoundings.visualBounds.x < scrollElement.scrollLeft - ) { - let scrollLeft: number = barBoundings.realBounds.x + this.settings.player.scrollOffsetX; - this._lastScroll = barBoundings.visualBounds.x; - this.uiFacade.scrollToX(scrollElement, scrollLeft, this.settings.player.scrollSpeed); - } - break; + // we need to put the transition to an own animation frame + // otherwise the stop animation above is not applied. + this.uiFacade.beginInvoke(() => { + if (beatCursor) { + beatCursor.transitionToX(duration / this.playbackSpeed, nextBeatX); } - } + }); } - // trigger an event for others to indicate which beat/bar is played + + shouldScroll = !stop; + shouldNotifyBeatChange = true; + } + + if (shouldScroll && !this._beatMouseDown && this.settings.player.scrollMode !== ScrollMode.Off) { + this.internalScrollToCursor(barBoundings); + } + + // trigger an event for others to indicate which beat/bar is played + if (shouldNotifyBeatChange) { this.onPlayedBeatChanged(beat); + this.onActiveBeatsChanged(new ActiveBeatsChangedEventArgs(beatsToHighlight)); } } public playedBeatChanged: IEventEmitterOfT = new EventEmitterOfT(); private onPlayedBeatChanged(beat: Beat): void { + if (this._isDestroyed) { + return; + } (this.playedBeatChanged as EventEmitterOfT).trigger(beat); this.uiFacade.triggerEvent(this.container, 'playedBeatChanged', beat); } + public activeBeatsChanged: IEventEmitterOfT = + new EventEmitterOfT(); + private onActiveBeatsChanged(e: ActiveBeatsChangedEventArgs): void { + if (this._isDestroyed) { + return; + } + (this.activeBeatsChanged as EventEmitterOfT).trigger(e); + this.uiFacade.triggerEvent(this.container, 'activeBeatsChanged', e); + } + private _beatMouseDown: boolean = false; + private _noteMouseDown: boolean = false; private _selectionStart: SelectionInfo | null = null; private _selectionEnd: SelectionInfo | null = null; @@ -957,7 +1081,15 @@ export class AlphaTabApiBase { public beatMouseMove: IEventEmitterOfT = new EventEmitterOfT(); public beatMouseUp: IEventEmitterOfT = new EventEmitterOfT(); + public noteMouseDown: IEventEmitterOfT = new EventEmitterOfT(); + public noteMouseMove: IEventEmitterOfT = new EventEmitterOfT(); + public noteMouseUp: IEventEmitterOfT = new EventEmitterOfT(); + private onBeatMouseDown(originalEvent: IMouseEventArgs, beat: Beat): void { + if (this._isDestroyed) { + return; + } + if ( this.settings.player.enablePlayer && this.settings.player.enableCursor && @@ -971,7 +1103,21 @@ export class AlphaTabApiBase { this.uiFacade.triggerEvent(this.container, 'beatMouseDown', beat, originalEvent); } + private onNoteMouseDown(originalEvent: IMouseEventArgs, note: Note): void { + if (this._isDestroyed) { + return; + } + + this._noteMouseDown = true; + (this.noteMouseDown as EventEmitterOfT).trigger(note); + this.uiFacade.triggerEvent(this.container, 'noteMouseDown', note, originalEvent); + } + private onBeatMouseMove(originalEvent: IMouseEventArgs, beat: Beat): void { + if (this._isDestroyed) { + return; + } + if (this.settings.player.enableUserInteraction) { if (!this._selectionEnd || this._selectionEnd.beat !== beat) { this._selectionEnd = new SelectionInfo(beat); @@ -982,12 +1128,25 @@ export class AlphaTabApiBase { this.uiFacade.triggerEvent(this.container, 'beatMouseMove', beat, originalEvent); } + private onNoteMouseMove(originalEvent: IMouseEventArgs, note: Note): void { + if (this._isDestroyed) { + return; + } + + (this.noteMouseMove as EventEmitterOfT).trigger(note); + this.uiFacade.triggerEvent(this.container, 'noteMouseMove', note, originalEvent); + } + private onBeatMouseUp(originalEvent: IMouseEventArgs, beat: Beat | null): void { + if (this._isDestroyed) { + return; + } + if (this.settings.player.enableUserInteraction) { // for the selection ensure start < end if (this._selectionEnd) { let startTick: number = this._selectionStart!.beat.absolutePlaybackStart; - let endTick: number = this._selectionStart!.beat.absolutePlaybackStart; + let endTick: number = this._selectionEnd!.beat.absolutePlaybackStart; if (endTick < startTick) { let t: SelectionInfo = this._selectionStart!; this._selectionStart = this._selectionEnd; @@ -1003,7 +1162,7 @@ export class AlphaTabApiBase { // move to selection start this._currentBeat = null; // reset current beat so it is updating the cursor if (this._playerState === PlayerState.Paused) { - this.cursorUpdateBeat(this._selectionStart.beat, null, 0, false, [this._selectionStart.beat]); + this.cursorUpdateTick(this._selectionStart.beat.absolutePlaybackStart, false); } this.tickPosition = realMasterBarStart + this._selectionStart.beat.playbackStart; // set playback range @@ -1033,6 +1192,16 @@ export class AlphaTabApiBase { this._beatMouseDown = false; } + private onNoteMouseUp(originalEvent: IMouseEventArgs, note: Note | null): void { + if (this._isDestroyed) { + return; + } + + (this.noteMouseUp as EventEmitterOfT).trigger(note); + this.uiFacade.triggerEvent(this.container, 'noteMouseUp', note, originalEvent); + this._noteMouseDown = false; + } + private updateSelectionCursor(range: PlaybackRange | null) { if (!this._tickCache) { return; @@ -1048,7 +1217,6 @@ export class AlphaTabApiBase { } else { this.cursorSelectRange(null, null); } - } private setupClickHandling(): void { @@ -1064,6 +1232,13 @@ export class AlphaTabApiBase { let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null; if (beat) { this.onBeatMouseDown(e, beat); + + if (this.settings.core.includeNoteBounds) { + const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY); + if (note) { + this.onNoteMouseDown(e, note); + } + } } }); this.canvasElement.mouseMove.on(e => { @@ -1075,6 +1250,13 @@ export class AlphaTabApiBase { let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null; if (beat) { this.onBeatMouseMove(e, beat); + + if (this._noteMouseDown) { + const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY); + if (note) { + this.onNoteMouseMove(e, note); + } + } } }); this.canvasElement.mouseUp.on(e => { @@ -1088,6 +1270,15 @@ export class AlphaTabApiBase { let relY: number = e.getY(this.canvasElement); let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null; this.onBeatMouseUp(e, beat); + + if (this._noteMouseDown) { + if (beat) { + const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY) ?? null; + this.onNoteMouseUp(e, note); + } else { + this.onNoteMouseUp(e, null); + } + } }); this.renderer.postRenderFinished.on(() => { if ( @@ -1145,76 +1336,102 @@ export class AlphaTabApiBase { // from the startbeat to the end of the staff, // then fill all staffs until the end-beat staff // then from staff-start to the end beat (or to end of bar if it's the last beat) - let staffStartX: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds.visualBounds.x; + let staffStartX: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.x; let staffEndX: number = - startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds.visualBounds.x + - startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds.visualBounds.w; + startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.x + + startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.w; let startSelection: IContainer = this.uiFacade.createSelectionElement()!; - startSelection.top = startBeat.bounds!.barBounds.masterBarBounds.visualBounds.y; - startSelection.left = startX; - startSelection.width = staffEndX - startX; - startSelection.height = startBeat.bounds!.barBounds.masterBarBounds.visualBounds.h; + startSelection.setBounds( + startX, + startBeat.bounds!.barBounds.masterBarBounds.visualBounds.y, + staffEndX - startX, + startBeat.bounds!.barBounds.masterBarBounds.visualBounds.h + ); selectionWrapper.appendChild(startSelection); - let staffStartIndex: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds.index + 1; - let staffEndIndex: number = endBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds.index; + let staffStartIndex: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.index + 1; + let staffEndIndex: number = endBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.index; for (let staffIndex: number = staffStartIndex; staffIndex < staffEndIndex; staffIndex++) { let staffBounds: StaveGroupBounds = cache.staveGroups[staffIndex]; let middleSelection: IContainer = this.uiFacade.createSelectionElement()!; - middleSelection.top = staffBounds.visualBounds.y; - middleSelection.left = staffStartX; - middleSelection.width = staffEndX - staffStartX; - middleSelection.height = staffBounds.visualBounds.h; + middleSelection.setBounds( + staffStartX, + staffBounds.visualBounds.y, + staffEndX - staffStartX, + staffBounds.visualBounds.h + ); selectionWrapper.appendChild(middleSelection); } let endSelection: IContainer = this.uiFacade.createSelectionElement()!; - endSelection.top = endBeat.bounds!.barBounds.masterBarBounds.visualBounds.y; - endSelection.left = staffStartX; - endSelection.width = endX - staffStartX; - endSelection.height = endBeat.bounds!.barBounds.masterBarBounds.visualBounds.h; + endSelection.setBounds( + staffStartX, + endBeat.bounds!.barBounds.masterBarBounds.visualBounds.y, + endX - staffStartX, + endBeat.bounds!.barBounds.masterBarBounds.visualBounds.h + ); selectionWrapper.appendChild(endSelection); } else { // if the beats are on the same staff, we simply highlight from the startbeat to endbeat let selection: IContainer = this.uiFacade.createSelectionElement()!; - selection.top = startBeat.bounds!.barBounds.masterBarBounds.visualBounds.y; - selection.left = startX; - selection.width = endX - startX; - selection.height = startBeat.bounds!.barBounds.masterBarBounds.visualBounds.h; + selection.setBounds( + startX, + startBeat.bounds!.barBounds.masterBarBounds.visualBounds.y, + endX - startX, + startBeat.bounds!.barBounds.masterBarBounds.visualBounds.h + ); selectionWrapper.appendChild(selection); } } public scoreLoaded: IEventEmitterOfT = new EventEmitterOfT(); private onScoreLoaded(score: Score): void { + if (this._isDestroyed) { + return; + } (this.scoreLoaded as EventEmitterOfT).trigger(score); this.uiFacade.triggerEvent(this.container, 'scoreLoaded', score); } public resize: IEventEmitterOfT = new EventEmitterOfT(); private onResize(e: ResizeEventArgs): void { + if (this._isDestroyed) { + return; + } (this.resize as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'resize', e); } public renderStarted: IEventEmitterOfT = new EventEmitterOfT(); private onRenderStarted(resize: boolean): void { + if (this._isDestroyed) { + return; + } (this.renderStarted as EventEmitterOfT).trigger(resize); this.uiFacade.triggerEvent(this.container, 'renderStarted', resize); } public renderFinished: IEventEmitterOfT = new EventEmitterOfT(); private onRenderFinished(renderingResult: RenderFinishedEventArgs): void { + if (this._isDestroyed) { + return; + } (this.renderFinished as EventEmitterOfT).trigger(renderingResult); this.uiFacade.triggerEvent(this.container, 'renderFinished', renderingResult); } public postRenderFinished: IEventEmitter = new EventEmitter(); private onPostRenderFinished(): void { + if (this._isDestroyed) { + return; + } (this.postRenderFinished as EventEmitter).trigger(); this.uiFacade.triggerEvent(this.container, 'postRenderFinished', null); } public error: IEventEmitterOfT = new EventEmitterOfT(); public onError(error: Error): void { + if (this._isDestroyed) { + return; + } Logger.error('API', 'An unexpected error occurred', error); (this.error as EventEmitterOfT).trigger(error); this.uiFacade.triggerEvent(this.container, 'error', error); @@ -1222,55 +1439,100 @@ export class AlphaTabApiBase { public playerReady: IEventEmitter = new EventEmitter(); private onPlayerReady(): void { + if (this._isDestroyed) { + return; + } (this.playerReady as EventEmitter).trigger(); this.uiFacade.triggerEvent(this.container, 'playerReady', null); } public playerFinished: IEventEmitter = new EventEmitter(); private onPlayerFinished(): void { + if (this._isDestroyed) { + return; + } (this.playerFinished as EventEmitter).trigger(); this.uiFacade.triggerEvent(this.container, 'playerFinished', null); } public soundFontLoaded: IEventEmitter = new EventEmitter(); private onSoundFontLoaded(): void { + if (this._isDestroyed) { + return; + } (this.soundFontLoaded as EventEmitter).trigger(); this.uiFacade.triggerEvent(this.container, 'soundFontLoaded', null); } public midiLoad: IEventEmitterOfT = new EventEmitterOfT(); - private onMidiLoad(e:MidiFile): void { + private onMidiLoad(e: MidiFile): void { + if (this._isDestroyed) { + return; + } (this.midiLoad as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'midiLoad', e); } public midiLoaded: IEventEmitterOfT = new EventEmitterOfT(); - private onMidiLoaded(e:PositionChangedEventArgs): void { + private onMidiLoaded(e: PositionChangedEventArgs): void { + if (this._isDestroyed) { + return; + } (this.midiLoaded as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'midiFileLoaded', e); } - public playerStateChanged: IEventEmitterOfT = new EventEmitterOfT< - PlayerStateChangedEventArgs - >(); + public playerStateChanged: IEventEmitterOfT = + new EventEmitterOfT(); private onPlayerStateChanged(e: PlayerStateChangedEventArgs): void { + if (this._isDestroyed) { + return; + } (this.playerStateChanged as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'playerStateChanged', e); } - public playerPositionChanged: IEventEmitterOfT = new EventEmitterOfT< - PositionChangedEventArgs - >(); + public playerPositionChanged: IEventEmitterOfT = + new EventEmitterOfT(); private onPlayerPositionChanged(e: PositionChangedEventArgs): void { - (this.playerPositionChanged as EventEmitterOfT).trigger(e); - this.uiFacade.triggerEvent(this.container, 'playerPositionChanged', e); + if (this._isDestroyed) { + return; + } + if (this.score !== null && this.tracks.length > 0) { + (this.playerPositionChanged as EventEmitterOfT).trigger(e); + this.uiFacade.triggerEvent(this.container, 'playerPositionChanged', e); + } } - public midiEventsPlayed: IEventEmitterOfT = new EventEmitterOfT< - MidiEventsPlayedEventArgs - >(); + public midiEventsPlayed: IEventEmitterOfT = + new EventEmitterOfT(); private onMidiEventsPlayed(e: MidiEventsPlayedEventArgs): void { + if (this._isDestroyed) { + return; + } (this.midiEventsPlayed as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'midiEventsPlayed', e); } + + public playbackRangeChanged: IEventEmitterOfT = + new EventEmitterOfT(); + private onPlaybackRangeChanged(e: PlaybackRangeChangedEventArgs): void { + if (this._isDestroyed) { + return; + } + (this.playbackRangeChanged as EventEmitterOfT).trigger(e); + this.uiFacade.triggerEvent(this.container, 'playbackRangeChanged', e); + } + + /** + * @internal + */ + public settingsUpdated: IEventEmitter = new EventEmitter(); + private onSettingsUpdated(): void { + if (this._isDestroyed) { + return; + } + (this.settingsUpdated as EventEmitter).trigger(); + this.uiFacade.triggerEvent(this.container, 'settingsUpdated', null); + } } diff --git a/src/AlphaTabError.ts b/src/AlphaTabError.ts index 69bd6c477..eb450b615 100644 --- a/src/AlphaTabError.ts +++ b/src/AlphaTabError.ts @@ -8,8 +8,8 @@ export class AlphaTabError extends Error { public inner: Error | null; public type: AlphaTabErrorType; - public constructor(type: AlphaTabErrorType, message: string, inner?: Error) { - super(message); + public constructor(type: AlphaTabErrorType, message: string | null = "", inner?: Error) { + super(message ?? ""); this.type = type; this.inner = inner ?? null; Object.setPrototypeOf(this, AlphaTabError.prototype); diff --git a/src/CoreSettings.ts b/src/CoreSettings.ts index 6b0ca2047..ea1a81044 100644 --- a/src/CoreSettings.ts +++ b/src/CoreSettings.ts @@ -31,7 +31,7 @@ export class CoreSettings { public tex: boolean = false; /** - * Gets or sets the initial tracks that should be loaded for the score. + * Gets or sets the initial tracks that should be loaded for the score. * @target web */ public tracks: unknown = null; @@ -96,7 +96,7 @@ export class CoreSettings { * @target web */ public static ensureFullUrl(relativeUrl: string | null): string { - if(!relativeUrl) { + if (!relativeUrl) { return ''; } diff --git a/src/DisplaySettings.ts b/src/DisplaySettings.ts index 2d3d8fafa..daca870af 100644 --- a/src/DisplaySettings.ts +++ b/src/DisplaySettings.ts @@ -1,45 +1,6 @@ import { RenderingResources } from '@src/RenderingResources'; - -/** - * Lists all stave profiles controlling which staves are shown. - */ -export enum StaveProfile { - /** - * The profile is auto detected by the track configurations. - */ - Default, - /** - * Standard music notation and guitar tablature are rendered. - */ - ScoreTab, - /** - * Only standard music notation is rendered. - */ - Score, - /** - * Only guitar tablature is rendered. - */ - Tab, - /** - * Only guitar tablature is rendered, but also rests and time signatures are not shown. - * This profile is typically used in multi-track scenarios. - */ - TabMixed -} - -/** - * Lists all layout modes that are supported. - */ -export enum LayoutMode { - /** - * Bars are aligned in rows using a fixed width. - */ - Page, - /** - * Bars are aligned horizontally in one row - */ - Horizontal -} +import { LayoutMode } from '@src/LayoutMode'; +import { StaveProfile } from '@src/StaveProfile'; /** * The display settings control how the general layout and display of alphaTab is done. diff --git a/src/Environment.ts b/src/Environment.ts index e66c26f37..9dc99eb59 100644 --- a/src/Environment.ts +++ b/src/Environment.ts @@ -1,4 +1,5 @@ -import { LayoutMode, StaveProfile } from '@src/DisplaySettings'; +import { LayoutMode } from '@src/LayoutMode'; +import { StaveProfile } from '@src/StaveProfile'; import { AlphaTexImporter } from '@src/importer/AlphaTexImporter'; import { Gp3To5Importer } from '@src/importer/Gp3To5Importer'; import { Gp7Importer } from '@src/importer/Gp7Importer'; @@ -41,20 +42,21 @@ import { WhammyBarEffectInfo } from '@src/rendering/effects/WhammyBarEffectInfo' import { WideBeatVibratoEffectInfo } from '@src/rendering/effects/WideBeatVibratoEffectInfo'; import { WideNoteVibratoEffectInfo } from '@src/rendering/effects/WideNoteVibratoEffectInfo'; import { EffectBarRendererInfo } from '@src/rendering/EffectBarRendererInfo'; -import { IScoreRenderer } from '@src/rendering/IScoreRenderer'; import { HorizontalScreenLayout } from '@src/rendering/layout/HorizontalScreenLayout'; import { PageViewLayout } from '@src/rendering/layout/PageViewLayout'; import { ScoreLayout } from '@src/rendering/layout/ScoreLayout'; import { ScoreBarRendererFactory } from '@src/rendering/ScoreBarRendererFactory'; import { ScoreRenderer } from '@src/rendering/ScoreRenderer'; import { TabBarRendererFactory } from '@src/rendering/TabBarRendererFactory'; -import { Settings } from '@src/Settings'; import { FontLoadingChecker } from '@src/util/FontLoadingChecker'; import { Logger } from '@src/Logger'; -import { LeftHandTapEffectInfo } from './rendering/effects/LeftHandTapEffectInfo'; -import { CapellaImporter } from './importer/CapellaImporter'; -import { ResizeObserverPolyfill } from './platform/javascript/ResizeObserverPolyfill'; -import { IntersectionObserverPolyfill } from './platform/javascript/IntersectionObserverPolyfill'; +import { LeftHandTapEffectInfo } from '@src/rendering/effects/LeftHandTapEffectInfo'; +import { CapellaImporter } from '@src/importer/CapellaImporter'; +import { ResizeObserverPolyfill } from '@src/platform/javascript/ResizeObserverPolyfill'; +import { WebPlatform } from '@src/platform/javascript/WebPlatform'; +import { IntersectionObserverPolyfill } from '@src/platform/javascript/IntersectionObserverPolyfill'; +import { AlphaSynthWebWorklet } from '@src/platform/javascript/AlphaSynthAudioWorkletOutput'; +import { AlphaTabError, AlphaTabErrorType } from './AlphaTabError'; export class LayoutEngineFactory { public readonly vertical: boolean; @@ -87,12 +89,12 @@ export class RenderEngineFactory { */ export class Environment { /** - * The font size of the music font in pixel. + * The font size of the music font in pixel. */ public static readonly MusicFontSize = 34; /** - * The scaling factor to use when rending raster graphics for sharper rendering on high-dpi displays. + * The scaling factor to use when rending raster graphics for sharper rendering on high-dpi displays. */ public static HighDpiFactor = 1; @@ -162,12 +164,15 @@ export class Environment { try { Environment._globalThis = globalThis; } catch (e) { - // global this not available + // globalThis not available } if (typeof Environment._globalThis === 'undefined') { Environment._globalThis = self; } + if (typeof Environment._globalThis === 'undefined') { + Environment._globalThis = global; + } if (typeof Environment._globalThis === 'undefined') { Environment._globalThis = window; } @@ -179,6 +184,16 @@ export class Environment { return this._globalThis; } + /** + * @target web + */ + public static webPlatform: WebPlatform = Environment.detectWebPlatform(); + + /** + * @target web + */ + public static isWebPackBundled: boolean = Environment.detectWebPack(); + /** * @target web */ @@ -187,9 +202,7 @@ export class Environment { /** * @target web */ - public static bravuraFontChecker: FontLoadingChecker = new FontLoadingChecker( - 'alphaTab' - ); + public static bravuraFontChecker: FontLoadingChecker = new FontLoadingChecker(['alphaTab']); /** * @target web @@ -201,11 +214,58 @@ export class Environment { /** * @target web */ + public static get isRunningInAudioWorklet(): boolean { + return 'AudioWorkletGlobalScope' in Environment.globalThis; + } + + /** + * @target web + */ + public static createAlphaTabWorker(scriptFile: string | null): Worker { + if (Environment.isWebPackBundled) { + // WebPack currently requires this exact syntax: new Worker(new URL(..., import.meta.url))) + // The module `@coderline/alphatab` will be resolved by WebPack to alphaTab consumed as library + // this will not work with CDNs because worker start scripts need to have the same origin like + // the current browser. + + // https://github.com/webpack/webpack/discussions/14066 + + return new Worker( + // @ts-ignore + /* webpackChunkName: "alphatab.worker" */ new URL('@coderline/alphatab', import.meta.url) + ); + } + + if (!scriptFile) { + throw new AlphaTabError(AlphaTabErrorType.General, "Could not detect alphaTab script file, cannot initialize renderer"); + } + + try { + if (Environment.webPlatform === WebPlatform.BrowserModule) { + const script: string = `import * as alphaTab from '${scriptFile}'`; + const blob: Blob = new Blob([script], { type: 'text/javascript' }); + return new Worker(URL.createObjectURL(blob), { type: 'module' }); + } else { + const script: string = `importScripts('${scriptFile}')`; + const blob: Blob = new Blob([script]); + return new Worker(URL.createObjectURL(blob)); + } + } + catch (e) { + Logger.warning('Rendering', 'Could not create inline worker, fallback to normal worker'); + return new Worker(scriptFile); + } + } + + /** + * @target web + * @partial + */ public static throttle(action: () => void, delay: number): () => void { let timeoutId: number = 0; return () => { - window.clearTimeout(timeoutId); - timeoutId = window.setTimeout(action, delay); + Environment.globalThis.clearTimeout(timeoutId); + timeoutId = Environment.globalThis.setTimeout(action, delay); }; } @@ -213,10 +273,27 @@ export class Environment { * @target web */ private static detectScriptFile(): string | null { - if (Environment.isRunningInWorker) { - return null; + // browser include as ES6 import + //