From f3d46e385c844f86984535e1de484f8fd179ac4a Mon Sep 17 00:00:00 2001 From: seay Date: Thu, 16 Jun 2022 01:12:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .nuke/parameters.json | 4 + Hsu.NullModemEmulator.sln | 44 + build.cmd | 7 + build.ps1 | 69 + build.sh | 62 + nuke/.editorconfig | 11 + nuke/Build.Github.cs | 23 + nuke/Build.cs | 182 +++ nuke/Configuration.cs | 16 + nuke/Directory.Build.props | 8 + nuke/Directory.Build.targets | 8 + nuke/Nuke.Build.csproj | 17 + nuke/Nuke.Build.csproj.DotSettings | 26 + package.json | 5 + .../Hsu.NullModemEmulator.Tests.csproj | 23 + src/Hsu.NullModemEmulator.Tests/UnitTest1.cs | 86 ++ src/Hsu.NullModemEmulator.Tests/Usings.cs | 1 + src/Hsu.NullModemEmulator/DeviceType.cs | 23 + .../FriendlyNameDescriptior.cs | 40 + .../Hsu.NullModemEmulator.csproj | 26 + .../NullModemEmulatorManager.cs | 495 +++++++ src/Hsu.NullModemEmulator/PortBuilder.cs | 207 +++ src/Hsu.NullModemEmulator/PortBus.cs | 67 + .../PortBusDescriptior.cs | 47 + src/Hsu.NullModemEmulator/PortBusOrder.cs | 23 + src/Hsu.NullModemEmulator/PortDescriptior.cs | 147 ++ src/Hsu.NullModemEmulator/RegistryHelper.cs | 22 + src/Hsu.NullModemEmulator/help.txt | 107 ++ yarn.lock | 1310 +++++++++++++++++ 29 files changed, 3106 insertions(+) create mode 100644 .nuke/parameters.json create mode 100644 Hsu.NullModemEmulator.sln create mode 100644 build.cmd create mode 100644 build.ps1 create mode 100644 build.sh create mode 100644 nuke/.editorconfig create mode 100644 nuke/Build.Github.cs create mode 100644 nuke/Build.cs create mode 100644 nuke/Configuration.cs create mode 100644 nuke/Directory.Build.props create mode 100644 nuke/Directory.Build.targets create mode 100644 nuke/Nuke.Build.csproj create mode 100644 nuke/Nuke.Build.csproj.DotSettings create mode 100644 package.json create mode 100644 src/Hsu.NullModemEmulator.Tests/Hsu.NullModemEmulator.Tests.csproj create mode 100644 src/Hsu.NullModemEmulator.Tests/UnitTest1.cs create mode 100644 src/Hsu.NullModemEmulator.Tests/Usings.cs create mode 100644 src/Hsu.NullModemEmulator/DeviceType.cs create mode 100644 src/Hsu.NullModemEmulator/FriendlyNameDescriptior.cs create mode 100644 src/Hsu.NullModemEmulator/Hsu.NullModemEmulator.csproj create mode 100644 src/Hsu.NullModemEmulator/NullModemEmulatorManager.cs create mode 100644 src/Hsu.NullModemEmulator/PortBuilder.cs create mode 100644 src/Hsu.NullModemEmulator/PortBus.cs create mode 100644 src/Hsu.NullModemEmulator/PortBusDescriptior.cs create mode 100644 src/Hsu.NullModemEmulator/PortBusOrder.cs create mode 100644 src/Hsu.NullModemEmulator/PortDescriptior.cs create mode 100644 src/Hsu.NullModemEmulator/RegistryHelper.cs create mode 100644 src/Hsu.NullModemEmulator/help.txt create mode 100644 yarn.lock diff --git a/.nuke/parameters.json b/.nuke/parameters.json new file mode 100644 index 0000000..4141633 --- /dev/null +++ b/.nuke/parameters.json @@ -0,0 +1,4 @@ +{ + "$schema": "./build.schema.json", + "Solution": "Hsu.NullModemEmulator.sln" +} \ No newline at end of file diff --git a/Hsu.NullModemEmulator.sln b/Hsu.NullModemEmulator.sln new file mode 100644 index 0000000..2a8659f --- /dev/null +++ b/Hsu.NullModemEmulator.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32516.85 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F448B1BE-34BC-4DAA-9070-E046122F707E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hsu.NullModemEmulator", "src\Hsu.NullModemEmulator\Hsu.NullModemEmulator.csproj", "{44E063A2-74B2-4A6C-8F6C-4E44E859F232}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hsu.NullModemEmulator.Tests", "src\Hsu.NullModemEmulator.Tests\Hsu.NullModemEmulator.Tests.csproj", "{35ADD154-9760-4857-951D-902DAE661376}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nuke.Build", "nuke\Nuke.Build.csproj", "{0BC066C6-BCFD-4ED1-AC54-EDCC0B93BCA9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuke", "nuke", "{18A17C99-D504-4E4D-9A6E-61D3C5DEE408}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {44E063A2-74B2-4A6C-8F6C-4E44E859F232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44E063A2-74B2-4A6C-8F6C-4E44E859F232}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44E063A2-74B2-4A6C-8F6C-4E44E859F232}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44E063A2-74B2-4A6C-8F6C-4E44E859F232}.Release|Any CPU.Build.0 = Release|Any CPU + {35ADD154-9760-4857-951D-902DAE661376}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35ADD154-9760-4857-951D-902DAE661376}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35ADD154-9760-4857-951D-902DAE661376}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35ADD154-9760-4857-951D-902DAE661376}.Release|Any CPU.Build.0 = Release|Any CPU + {0BC066C6-BCFD-4ED1-AC54-EDCC0B93BCA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BC066C6-BCFD-4ED1-AC54-EDCC0B93BCA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {44E063A2-74B2-4A6C-8F6C-4E44E859F232} = {F448B1BE-34BC-4DAA-9070-E046122F707E} + {35ADD154-9760-4857-951D-902DAE661376} = {F448B1BE-34BC-4DAA-9070-E046122F707E} + {0BC066C6-BCFD-4ED1-AC54-EDCC0B93BCA9} = {18A17C99-D504-4E4D-9A6E-61D3C5DEE408} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CD0A83CA-EC16-4A8E-989A-8167E0DAB0BD} + EndGlobalSection +EndGlobal diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..b08cc59 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +:; set -eo pipefail +:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +:; ${SCRIPT_DIR}/build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..d9ed34b --- /dev/null +++ b/build.ps1 @@ -0,0 +1,69 @@ +[CmdletBinding()] +Param( + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$BuildArguments +) + +Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" + +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + +########################################################################### +# CONFIGURATION +########################################################################### + +$BuildProjectFile = "$PSScriptRoot\nuke\Nuke.Build.csproj" +$TempDirectory = "$PSScriptRoot\\.nuke\temp" + +$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" +$DotNetChannel = "Current" + +$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 +$env:DOTNET_MULTILEVEL_LOOKUP = 0 + +########################################################################### +# EXECUTION +########################################################################### + +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` + $(dotnet --version) -and $LASTEXITCODE -eq 0) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path +} +else { + # Download install script + $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" + New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) + + # If global.json exists, load expected version + if (Test-Path $DotNetGlobalFile) { + $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) + if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { + $DotNetVersion = $DotNetGlobal.sdk.version + } + } + + # Install by channel or version + $DotNetDirectory = "$TempDirectory\dotnet-win" + if (!(Test-Path variable:DotNetVersion)) { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } + } else { + ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } + } + $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" +} + +Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" + +ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..67b0668 --- /dev/null +++ b/build.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +bash --version 2>&1 | head -n 1 + +set -eo pipefail +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) + +########################################################################### +# CONFIGURATION +########################################################################### + +BUILD_PROJECT_FILE="$SCRIPT_DIR/nuke/Nuke.Build.csproj" +TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" + +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" +DOTNET_CHANNEL="Current" + +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +export DOTNET_MULTILEVEL_LOOKUP=0 + +########################################################################### +# EXECUTION +########################################################################### + +function FirstJsonValue { + perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" +} + +# If dotnet CLI is installed globally and it matches requested version, use for execution +if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then + export DOTNET_EXE="$(command -v dotnet)" +else + # Download install script + DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" + mkdir -p "$TEMP_DIRECTORY" + curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" + chmod +x "$DOTNET_INSTALL_FILE" + + # If global.json exists, load expected version + if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then + DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") + if [[ "$DOTNET_VERSION" == "" ]]; then + unset DOTNET_VERSION + fi + fi + + # Install by channel or version + DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" + if [[ -z ${DOTNET_VERSION+x} ]]; then + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path + else + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path + fi + export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" +fi + +echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" + +"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/nuke/.editorconfig b/nuke/.editorconfig new file mode 100644 index 0000000..31e43dc --- /dev/null +++ b/nuke/.editorconfig @@ -0,0 +1,11 @@ +[*.cs] +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_require_accessibility_modifiers = never:warning + +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning diff --git a/nuke/Build.Github.cs b/nuke/Build.Github.cs new file mode 100644 index 0000000..229dda9 --- /dev/null +++ b/nuke/Build.Github.cs @@ -0,0 +1,23 @@ +using Nuke.Common.CI.GitHubActions; + +[GitHubActions( + "continuous", + GitHubActionsImage.WindowsLatest, + AutoGenerate = true, + PublishArtifacts = true, + // On = new[] { GitHubActionsTrigger.Push }, + OnPushBranches = new[] { "main" }, + InvokedTargets = new[] { nameof(Deploy) }, + ImportSecrets = new[] { nameof(GitAccessToken), nameof(NuGetApiKey), nameof(MyGetApiKey) }, + CacheKeyFiles = new string[0] +)] +internal partial class Build +{ + //private Target Release => _ => _ + // .Description("Release") + // .Executes(() => + // { + // GitReleaseManagerCreate(new Nuke.Common.Tools.GitReleaseManager.GitReleaseManagerCreateSettings()); + // //GitReleaseManagerAddAssets( ) + // }); +} \ No newline at end of file diff --git a/nuke/Build.cs b/nuke/Build.cs new file mode 100644 index 0000000..9164c8f --- /dev/null +++ b/nuke/Build.cs @@ -0,0 +1,182 @@ +using Nuke.Common; +using Nuke.Common.CI; +using Nuke.Common.CI.AzurePipelines; +using Nuke.Common.IO; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tooling; +using Nuke.Common.Tools.DotNet; +using Nuke.Common.Tools.MSBuild; +using Nuke.Common.Utilities.Collections; + +using Serilog; + +using System; +using System.Linq; + +using static Nuke.Common.IO.FileSystemTasks; +using static Nuke.Common.IO.PathConstruction; +using static Nuke.Common.Tools.DotNet.DotNetTasks; +using static Nuke.Common.Tools.MSBuild.MSBuildTasks; + +[ShutdownDotNetAfterServerBuild] +internal partial class Build : NukeBuild +{ + /// Support plugins are available for: + /// - JetBrains ReSharper https://nuke.build/resharper + /// - JetBrains Rider https://nuke.build/rider + /// - Microsoft VisualStudio https://nuke.build/visualstudio + /// - Microsoft VSCode https://nuke.build/vscode + + public static int Main() => Execute(x => x.Push); + + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + private readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + + [Parameter("Api key to push packages to nuget.org.")] + [Secret] + private string NuGetApiKey; + + [Parameter("Api key to push packages to myget.org.")] + [Secret] + private string MyGetApiKey; + + [Parameter("Github personal access token.")] + [Secret] + private string GitAccessToken; + + [CI] private readonly AzurePipelines AzurePipelines; + [Solution] private readonly Solution Solution; + [PathExecutable] private readonly Tool Cmd; + + private AbsolutePath SourceDirectory => RootDirectory / "src"; + private AbsolutePath OutputDirectory => RootDirectory / "output"; + private AbsolutePath ArtifactsDirectory => RootDirectory / "artifacts"; + + protected override void OnBuildInitialized() + { + base.OnBuildInitialized(); + NuGetApiKey ??= Environment.GetEnvironmentVariable(nameof(NuGetApiKey)); + MyGetApiKey ??= Environment.GetEnvironmentVariable(nameof(MyGetApiKey)); + GitAccessToken ??= Environment.GetEnvironmentVariable(nameof(GitAccessToken)); + } + + private Target Initial => _ => _ + .Description("Initial") + .OnlyWhenStatic(() => IsServerBuild) + .Executes(() => + { + AbsolutePath x86 = (AbsolutePath)Environment.GetFolderPath(Environment.SpecialFolder.SystemX86); + x86 /= "regsvr32.exe"; + AbsolutePath x64 = (AbsolutePath)Environment.GetFolderPath(Environment.SpecialFolder.System); + x64 /= "regsvr32.exe"; + + ProcessTasks.StartProcess(x64, $"/s {RootDirectory / "tools" / "graybox" / "x64" / "gbda_aut.dll"}"); + ProcessTasks.StartProcess(x86, $"/s {RootDirectory / "tools" / "graybox" / "x86" / "gbda_aut.dll"}"); + ProcessTasks.StartProcess(x86, $"/s {RootDirectory / "tools" / "OPCDAAuto.dll"}"); + ProcessTasks.StartProcess(x86, $"/s {RootDirectory / "tools" / "kepopcdaauto.dll"}"); + }); + + private Target Clean => _ => _ + .Description("Clean Solution") + .DependsOn(Initial) + .Executes(() => + { + SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(DeleteDirectory); + EnsureCleanDirectory(OutputDirectory); + EnsureCleanDirectory(ArtifactsDirectory); + }); + + private Target Restore => _ => _ + .Description("Restore Solution") + .DependsOn(Clean) + .Executes(() => + { + MSBuild(s => s + .SetTargetPath(Solution) + .SetTargets("Restore")); + }); + + private Target Compile => _ => _ + .Description("Compile Solution") + .DependsOn(Restore) + .Executes(() => + { + MSBuild(s => s + .SetTargetPath(Solution) + .SetTargets("Rebuild") + .SetConfiguration(Configuration) + .SetMaxCpuCount(Environment.ProcessorCount) + .SetNodeReuse(IsLocalBuild)); + }); + + //private Target Pack => _ => _ + // .Description("Pack NuGet Package") + // .DependsOn(Compile) + // .Executes(() => + // { + // MSBuild(s => s + // .SetTargetPath(Solution) + // .SetTargets("Pack") + // .SetConfiguration(Configuration) + // .SetMaxCpuCount(Environment.ProcessorCount) + // .SetNodeReuse(IsLocalBuild)); + // }); + + private Target Copy => _ => _ + .Description("Copy NuGet Package") + .OnlyWhenStatic(() => IsServerBuild, () => Configuration.Equals(Configuration.Release)) + .DependsOn(Compile) + .Executes(() => + { + GlobFiles(OutputDirectory, "**/*.nupkg") + ?.Where(x => !x.EndsWith(".symbols.nupkg")) + .ForEach(x => CopyFileToDirectory(x, ArtifactsDirectory / "packages", FileExistsPolicy.OverwriteIfNewer)); + }); + + private Target Artifacts => _ => _ + .DependsOn(Copy) + .OnlyWhenStatic(() => IsServerBuild) + .Description("Upload Artifacts") + .Executes(() => + { + Log.Information("Upload artifacts to azure..."); + AzurePipelines + .UploadArtifacts("artifacts", "artifacts", ArtifactsDirectory); + Log.Information("Upload artifacts to azure finished."); + }); + + private Target Push => _ => _ + .Description("Push NuGet Package") + .OnlyWhenStatic(() => IsServerBuild, () => Configuration.Equals(Configuration.Release)) + .DependsOn(Copy) + .Requires(() => NuGetApiKey) + .Requires(() => MyGetApiKey) + .Executes(() => + { + GlobFiles(ArtifactsDirectory / "packages", "**/*.nupkg") + ?.Where(x => !x.EndsWith(".symbols.nupkg")) + .ForEach(Nuget); + }); + + private Target Deploy => _ => _ + .Description("Deploy") + .DependsOn(Push, Artifacts) + .Executes(() => + { + Log.Information("Deployed"); + }); + + private void Nuget(string x) + { + Nuget(x, "https://www.myget.org/F/godsharp/api/v2/package", MyGetApiKey); + Nuget(x, "https://api.nuget.org/v3/index.json", NuGetApiKey); + } + + private void Nuget(string x, string source, string key) => + DotNetNuGetPush(s => s + .SetTargetPath(x) + .SetSource(source) + .SetApiKey(key) + .SetSkipDuplicate(true) + ); +} \ No newline at end of file diff --git a/nuke/Configuration.cs b/nuke/Configuration.cs new file mode 100644 index 0000000..9c08b1a --- /dev/null +++ b/nuke/Configuration.cs @@ -0,0 +1,16 @@ +using System; +using System.ComponentModel; +using System.Linq; +using Nuke.Common.Tooling; + +[TypeConverter(typeof(TypeConverter))] +public class Configuration : Enumeration +{ + public static Configuration Debug = new Configuration { Value = nameof(Debug) }; + public static Configuration Release = new Configuration { Value = nameof(Release) }; + + public static implicit operator string(Configuration configuration) + { + return configuration.Value; + } +} diff --git a/nuke/Directory.Build.props b/nuke/Directory.Build.props new file mode 100644 index 0000000..e147d63 --- /dev/null +++ b/nuke/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/nuke/Directory.Build.targets b/nuke/Directory.Build.targets new file mode 100644 index 0000000..2532609 --- /dev/null +++ b/nuke/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/nuke/Nuke.Build.csproj b/nuke/Nuke.Build.csproj new file mode 100644 index 0000000..f91c463 --- /dev/null +++ b/nuke/Nuke.Build.csproj @@ -0,0 +1,17 @@ + + + + Exe + net6.0 + + CS0649;CS0169 + .. + .. + 1 + + + + + + + diff --git a/nuke/Nuke.Build.csproj.DotSettings b/nuke/Nuke.Build.csproj.DotSettings new file mode 100644 index 0000000..c8947fc --- /dev/null +++ b/nuke/Nuke.Build.csproj.DotSettings @@ -0,0 +1,26 @@ + + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + Implicit + Implicit + ExpressionBody + 0 + NEXT_LINE + True + False + 120 + IF_OWNER_IS_SINGLE_LINE + WRAP_IF_LONG + False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True diff --git a/package.json b/package.json new file mode 100644 index 0000000..1141065 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "docsify-cli": "^4.4.4" + } +} diff --git a/src/Hsu.NullModemEmulator.Tests/Hsu.NullModemEmulator.Tests.csproj b/src/Hsu.NullModemEmulator.Tests/Hsu.NullModemEmulator.Tests.csproj new file mode 100644 index 0000000..bbb650e --- /dev/null +++ b/src/Hsu.NullModemEmulator.Tests/Hsu.NullModemEmulator.Tests.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/src/Hsu.NullModemEmulator.Tests/UnitTest1.cs b/src/Hsu.NullModemEmulator.Tests/UnitTest1.cs new file mode 100644 index 0000000..d299f80 --- /dev/null +++ b/src/Hsu.NullModemEmulator.Tests/UnitTest1.cs @@ -0,0 +1,86 @@ +using System.IO.Ports; + +namespace Hsu.NullModemEmulator.Tests; + +[TestClass] +public class UnitTest1 +{ + [TestMethod] + public void AllPortsTest() + { + var ports = SerialPort.GetPortNames(); + foreach (var item in ports) + { + Console.WriteLine(item); + } + } + + [TestMethod] + public async Task HelpAsyncTest() + { + NullModemEmulatorManager manager = new(); + var list = await manager.HelpAsync(); + foreach (var item in list) + { + Console.WriteLine(item); + } + } + + [TestMethod] + public async Task ListAsyncTest() + { + NullModemEmulatorManager manager = new(); + var list = await manager.ListAsync(); + foreach (var item in list) + { + Console.WriteLine(item); + Console.WriteLine(item.A); + Console.WriteLine(item.B); + } + } + + [TestMethod] + public async Task ListFriendlyNameAsyncTest() + { + NullModemEmulatorManager manager = new(); + var list = await manager.ListFriendlyNameAsync(); + foreach (var item in list) + { + Console.WriteLine(item); + } + } + + [TestMethod] + public async Task UpdateFriendlyNameAsyncTest() + { + NullModemEmulatorManager manager = new(); + await manager.UpdateFriendlyNameAsync(); + } + + [TestMethod] + public async Task AddPairAsyncTest() + { + NullModemEmulatorManager manager = new(); + PortBuilder builder = new(); + builder.PortName("COM7"); + var ret = await manager.AddPairAsync( + new PortBuilder() + .PortName("COM7") + .EmulateBaudRate(true) + , + new PortBuilder() + .PortName("COM8") + .EmulateBaudRate(true) + ); + Assert.IsTrue(ret); + } + + [TestMethod] + public async Task RemoveAsyncTest() + { + NullModemEmulatorManager manager = new(); + await manager.ListAsync(); + var ret = await manager.RemoveAsync(1); + Assert.IsTrue(ret); + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator.Tests/Usings.cs b/src/Hsu.NullModemEmulator.Tests/Usings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/src/Hsu.NullModemEmulator.Tests/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/DeviceType.cs b/src/Hsu.NullModemEmulator/DeviceType.cs new file mode 100644 index 0000000..694d5bf --- /dev/null +++ b/src/Hsu.NullModemEmulator/DeviceType.cs @@ -0,0 +1,23 @@ +namespace Hsu.NullModemEmulator; + +/// +/// The type of device +///
+/// 设备类型 +///
+public enum DeviceType +{ + /// + /// Virtual port + ///
+ /// 虚拟串口 + ///
+ Port, + + /// + /// Virtual port bus + ///
+ /// 虚拟串口对总线 + ///
+ Bus +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/FriendlyNameDescriptior.cs b/src/Hsu.NullModemEmulator/FriendlyNameDescriptior.cs new file mode 100644 index 0000000..52e8fa2 --- /dev/null +++ b/src/Hsu.NullModemEmulator/FriendlyNameDescriptior.cs @@ -0,0 +1,40 @@ +namespace Hsu.NullModemEmulator; + +/// +/// The friendly name descriptor for bus and port +///
+/// 虚拟串口对和虚拟串口的友好名称描述符 +///
+public record struct FriendlyNameDescriptior +{ + /// + /// Identity + ///
+ /// 标识 + ///
+ public int Id { get; set; } + /// + /// Name + ///
+ /// 名称 + ///
+ public string Name { get; set; } + /// + /// Friendly Name + ///
+ /// 友好名称 + ///
+ public string FriendlyName { get; set; } + /// + /// Device type + ///
+ /// 设备类型 + ///
+ public DeviceType Type { get; set; } + /// + /// Device order + ///
+ /// 虚拟串口顺序 + ///
+ public PortBusOrder? Order { get; set; } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/Hsu.NullModemEmulator.csproj b/src/Hsu.NullModemEmulator/Hsu.NullModemEmulator.csproj new file mode 100644 index 0000000..dfcf59d --- /dev/null +++ b/src/Hsu.NullModemEmulator/Hsu.NullModemEmulator.csproj @@ -0,0 +1,26 @@ + + + + netstandard2.0;net461; + git + https://github.com/godsharp/opcsample.git + https://github.com/godsharp/opcsample + https://avatars3.githubusercontent.com/u/26563296 + latest + GodSharp + seayxu + Copyright © GodSharp 2022 + $(SolutionDir)output\$(AssemblyName) + true + + + + + + + + + + + + diff --git a/src/Hsu.NullModemEmulator/NullModemEmulatorManager.cs b/src/Hsu.NullModemEmulator/NullModemEmulatorManager.cs new file mode 100644 index 0000000..7eaa813 --- /dev/null +++ b/src/Hsu.NullModemEmulator/NullModemEmulatorManager.cs @@ -0,0 +1,495 @@ +using CliWrap; +using CliWrap.Buffered; + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Hsu.NullModemEmulator; + +/// +/// The virtual port manager +///
+/// 虚拟串口管理器 +///
+public class NullModemEmulatorManager +{ + private string _path { get; set; } + private string _setupc { get; set; } + + private ConcurrentDictionary _pairs; + + /// + /// The pair of ports. + ///
+ /// 虚拟串口对 + ///
+ public IReadOnlyDictionary Pairs => _pairs; + + /// + /// Initialize the NullModemEmulatorManager + ///
+ /// 初始化 com0com 管理 + ///
+ public NullModemEmulatorManager() + { + _pairs = new(); + Initial(); + } + + /// + /// Initialize the NullModemEmulatorManager + ///
+ /// 初始化 com0com 管理 + ///
+ /// + /// The root directory of com0com.exe + ///
+ /// com0com.exe 安装目录 + /// + public NullModemEmulatorManager(string path) + { + _pairs = new(); + SetRoot(path); + } + + /// + /// Initialize the root path of the NullModemEmulator + ///
+ /// 初始化,默认取注册表中安装路径 + ///
+ public void Initial() + { + SetRoot(RegistryHelper.GetInstallPath()); + } + + private void SetRoot(string path) + { + if (!Directory.Exists(path)) throw new DirectoryNotFoundException(); + _path = path ?? throw new FileNotFoundException("the install path of com0com not found."); + var tmp = Path.Combine(_path, "setupc.exe"); + if (!File.Exists(_setupc) == false) throw new FileNotFoundException("the path of setupc.exe for com0com not found."); + _setupc = tmp; + } + + /// + /// Custom directory of com0com. + ///
+ /// 自定义 com0com 根目录 + ///
+ /// + public void CustomRoot(string path) + { + SetRoot(path); + } + + /// + /// Create a command. + /// + /// The arguments + /// + private Command GetCommand(params string[] values) + { + return Cli.Wrap(_setupc) + .WithWorkingDirectory(_path) + .WithArguments(args => args + .Add($"--output \"{Path.Combine(Directory.GetCurrentDirectory(), "nme.log")}\"") + .Add("--silent") + .Add(values) + ); + } + + /// + /// Print help information. + ///
+ /// 打印帮助信息 + ///
+ /// + public async Task HelpAsync() + { + var result = await GetCommand("help").ExecuteBufferedAsync(); + return result.StandardOutput; + } + + /// + /// List all the virtual ports. + ///
+ /// 获取全部虚拟串口对 + ///
+ /// + /// The array of virtual ports pair. + ///
+ /// 返回串口对数组 + ///
+ public async Task ListAsync() + { + var result = await GetCommand("--detail-prms list").ExecuteBufferedAsync(); + var lines = result.StandardOutput.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + _pairs.Clear(); + foreach (var item in lines) + { + //CNCA0 PortName=COM1,EmuBR=no,EmuOverrun=no,PlugInMode=no,ExclusiveMode=no,HiddenMode=no,AllDataBits=no,cts=rrts,dsr=rdtr,dcd=rdtr,ri=!on,EmuNoise=0,AddRTTO=0,AddRITO=0 + if (string.IsNullOrWhiteSpace(item)) continue; + + PortDescriptior descriptior = new(); + int index = 0; + var segments = item.Split(','); + + var tmp = segments[index++].Trim().Split('='); + descriptior.DeviceName = tmp[0].Split(' ')[0]; + descriptior.BusId = int.Parse(descriptior.DeviceName.Substring(4)); + descriptior.BusOrder = descriptior.DeviceName.Substring(3, 1) == "A" ? PortBusOrder.A : PortBusOrder.B; + descriptior.PortName = tmp[1]; + + tmp = segments[index++].Trim().Split('='); + descriptior.EmulateBaudRate = tmp[1] == "yes"; + + tmp = segments[index++].Trim().Split('='); + descriptior.EmulateOverrun = tmp[1] == "yes"; + + tmp = segments[index++].Trim().Split('='); + descriptior.PlugInMode = tmp[1] == "yes"; + + tmp = segments[index++].Trim().Split('='); + descriptior.ExclusiveMode = tmp[1] == "yes"; + + tmp = segments[index++].Trim().Split('='); + descriptior.HideMode = tmp[1] == "yes"; + + tmp = segments[index++].Trim().Split('='); + descriptior.AllDataBits = tmp[1] == "yes"; + + if (!_pairs.TryGetValue(descriptior.BusId, out var pair) || pair == null) + { + pair = new(descriptior.BusId); + _pairs.TryAdd(descriptior.BusId, pair); + } + + switch (descriptior.BusOrder) + { + case PortBusOrder.A: + pair.A = descriptior; + break; + + case PortBusOrder.B: + pair.B = descriptior; + break; + } + } + + return _pairs.Values.ToArray(); + } + + /// + /// List friendly names of all the virtual ports. + ///
+ /// 获取全部虚拟串口对的友好名称 + ///
+ /// + /// The friendly names array of virtual ports pair. + ///
+ /// 串口对友好名称数组 + ///
+ public async Task ListFriendlyNameAsync() + { + try + { + var result = await GetCommand("--detail-prms listfnames").ExecuteBufferedAsync(); + var lines = result.StandardOutput.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + List descriptiors = new(lines.Length); + + foreach (var item in lines) + { + /* + CNCBUS0 FriendlyName="com0com - bus for serial port pair emulator 0 (COM1 <-> COM2)" + CNCA0 FriendlyName="com0com - serial port emulator CNCA0 (COM1)" + CNCB0 FriendlyName="com0com - serial port emulator CNCB0 (COM2)" + */ + if (string.IsNullOrWhiteSpace(item)) continue; + + FriendlyNameDescriptior descriptior = new(); + var segments = item.Split('='); + int index = 0; + var tmp = segments[index++].Trim().Split(' '); + descriptior.Name = tmp[0]; + if (descriptior.Name.StartsWith("CNCBUS", StringComparison.OrdinalIgnoreCase)) + { + descriptior.Type = DeviceType.Bus; + } + else + { + descriptior.Type = DeviceType.Port; + descriptior.Order = descriptior.Name.StartsWith("CNCA", StringComparison.OrdinalIgnoreCase) ? PortBusOrder.A : PortBusOrder.B; + } + + descriptior.Id = int.Parse(tmp[0].Replace("CNCBUS", "").Replace("CNCA", "").Replace("CNCB", "")); + + descriptior.FriendlyName = segments[index].Trim(); + + PortBusDescriptior bus; + if (!descriptiors.Exists(x => x.Id == descriptior.Id)) + { + bus = new PortBusDescriptior(descriptior.Id); + descriptiors.Add(bus); + } + else + { + bus = descriptiors.First(x => x.Id == descriptior.Id); + } + + switch (descriptior.Type) + { + case DeviceType.Bus: + bus.Bus = descriptior; + break; + + case DeviceType.Port: + switch (descriptior.Order) + { + case PortBusOrder.A: + bus.A = descriptior; + break; + + case PortBusOrder.B: + bus.B = descriptior; + break; + } + break; + } + } + + return descriptiors.ToArray(); + } + finally + { + await ListAsync(); + } + } + + /// + /// Update the friendly name of the virtual port. + ///
+ /// 更新虚拟串口的友好名称 + ///
+ /// + public async Task UpdateFriendlyNameAsync() + { + /* + .\setupc.exe updatefnames + CNCBUS0 FriendlyName="com0com - bus for serial port pair emulator 0 (COM1 <-> COM2)" + CNCA0 FriendlyName="com0com - serial port emulator CNCA0 (COM1)" + CNCB0 FriendlyName="com0com - serial port emulator CNCB0 (COM2)" + CNCBUS5 FriendlyName="com0com - bus for serial port pair emulator 5 (COM5 <-> COM6)" + CNCA5 FriendlyName="com0com - serial port emulator CNCA5 (COM5)" + CNCB5 FriendlyName="com0com - serial port emulator CNCB5 (COM6)" + */ + await GetCommand($"updatefnames").ExecuteBufferedAsync(); + } + + /// + /// List busy port name. + ///
+ /// 获取正在使用的虚拟串口名称 + ///
+ /// + /// The filter for port name + ///
+ /// 串口名称过滤器 + /// + /// + /// The prefix of filter + ///
+ /// 名称过滤器前缀 + /// + /// + public async Task BusyNamesAsync(int? filter = null, string prefix = "COM") + { + var result = await GetCommand($"--detail-prms busynames {prefix}{(!filter.HasValue ? "*?" : filter.Value)}").ExecuteBufferedAsync(); + var lines = result.StandardOutput.Split(new char[] { '\n', ' ' }, StringSplitOptions.RemoveEmptyEntries); + return lines; + } + + /// + /// Add a virtual port pair. + ///
+ /// 添加一个虚拟串口对 + ///
+ /// + /// The first port of the pair. + ///
+ /// 第一个串口 + /// + /// + /// The second port of the pair. + ///
+ /// 第二个串口 + /// + /// + /// The id of the pair,default is -1,automatically assigned by the system. + ///
+ /// 指定串口对的id,默认为-1,由系统自动分配 + /// + /// + /// + public async Task AddPairAsync(PortBuilder a, PortBuilder b, int id = -1) + { + /* + * --detail-prms + CNCA1 PortName=COM3,EmuBR=no,EmuOverrun=no,PlugInMode=no,ExclusiveMode=no,HiddenMode=no,AllDataBits=no,cts=rrts,dsr=rdtr,dcd=rdtr,ri=!on,EmuNoise=0,AddRTTO=0,AddRITO=0 + CNCB1 PortName=COM4,EmuBR=no,EmuOverrun=no,PlugInMode=no,ExclusiveMode=no,HiddenMode=no,AllDataBits=no,cts=rrts,dsr=rdtr,dcd=rdtr,ri=!on,EmuNoise=0,AddRTTO=0,AddRITO=0 + ComDB: COM3 - logged as "in use" + ComDB: COM4 - logged as "in use" + + CNCA2 PortName=COM5 + CNCB2 PortName=COM6 + ComDB: COM5 - logged as "in use" + ComDB: COM6 - logged as "in use" + + DIALOG: { + The port name COM3 is already used for other device \Device\com0com11. + } ... ERROR + + Install not completed! + + */ + + try + { + if (id >= 0 && _pairs.ContainsKey(id)) throw new ArgumentException("the id of pair existed.", nameof(id)); + var result = await GetCommand($"install{(id < 0 ? "" : $" {id}")} {a} {b}").ExecuteBufferedAsync(); + await UpdateFriendlyNameAsync(); + return !result.StandardOutput.Contains("DIALOG"); + } + finally + { + await ListAsync(); + } + } + + /// + /// To change a virtual port parameters. + ///
+ /// 改变虚拟串口的参数 + ///
+ /// + /// The value of the pair id. + ///
+ /// 串口对标识 + /// + /// + /// The order of the port. + ///
+ /// 串口的顺序 + /// + /// + /// The parameters will changed. + ///
+ /// 要改变的参数 + /// + /// + public async Task ChangeAsync(int id, PortBusOrder order, PortBuilder builder) + { + /* + change CNCA0 EmuBR=yes,EmuOverrun=yes + + CNCA0 PortName=COM1,EmuBR=yes,EmuOverrun=yes,cts=rrts,ri=!on + CNCB0 PortName=COM2,EmuBR=yes + + change CNCA0 EmuBR=no,EmuOverrun=ye1s + + CNCA0 PortName=COM1,EmuBR=yes,EmuOverrun=yes,cts=rrts,ri=!on + Invalid value 'ye1s' + CNCB0 PortName=COM2,EmuBR=yes + */ + try + { + var result = await GetCommand($"change CNC{order}{id} {builder}").ExecuteBufferedAsync(); + return !result.StandardOutput.Contains("Invalid"); + } + finally + { + await ListAsync(); + } + } + + /// + /// Remove a virtual port pair. + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private async Task RemoveInternalAsync(int id) + { + /* + Disabled root\com0com \Device\00000278 + Removed root\com0com \Device\00000278 + Removed CNCA2 com0com\port + Removed CNCB2 com0com\port + ComDB: COM5 - released + ComDB: COM6 - released + */ + + if (!_pairs.Any(x => x.Key == id)) + { + throw new ArgumentOutOfRangeException(nameof(id), $"the pair of {id} is not exist."); + } + var _cmd = GetCommand($"remove {id}"); + Console.WriteLine(_cmd); + + var result = await _cmd.ExecuteBufferedAsync(); + var lines = result.StandardOutput.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + var ret = lines.Count(x => x.StartsWith("Removed")) == 3; + return ret; + } + + /// + /// Remove a virtual port pair. + ///
+ /// 移除一个虚拟串口对 + ///
+ /// + /// The value of the pair id. + ///
+ /// 虚拟串口对的标识 + /// + /// + public async Task RemoveAsync(int id) + { + try + { + return await RemoveInternalAsync(id); + } + finally + { + await ListAsync(); + } + } + + /// + /// Remove all virtual port pair. + ///
+ /// 移除全部虚拟串口对 + ///
+ /// + public async Task RemoveAllAsync() + { + try + { + bool ret = true; + foreach (var item in _pairs) + { + ret &= await RemoveInternalAsync(item.Key); + } + return ret; + } + finally + { + await ListAsync(); + } + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/PortBuilder.cs b/src/Hsu.NullModemEmulator/PortBuilder.cs new file mode 100644 index 0000000..34244c5 --- /dev/null +++ b/src/Hsu.NullModemEmulator/PortBuilder.cs @@ -0,0 +1,207 @@ +using System.Collections.Concurrent; +using System.Linq; +using System.Text; + +namespace Hsu.NullModemEmulator; + +/// +/// The virtual port builder +///
+/// 虚拟串口构建器 +///
+public class PortBuilder +{ + private ConcurrentDictionary _arguments { get; set; } + + /// + /// The virtual port builder + ///
+ /// 虚拟串口构建器 + ///
+ public PortBuilder() + { + _arguments = new(); + } + + /// + /// Reset arguments + ///
+ /// 重置参数 + ///
+ public void Reset() + { + _arguments.Clear(); + } + + /// + /// Set port name + ///
+ /// 设置串口号 + ///
+ /// + /// The port name + ///
+ /// 串口号 + /// + /// + public PortBuilder PortName(string portName) + { + return WithArgument("PortName", portName); + } + + /// + /// Enable/disable baud rate emulation in the direction to the paired port(disabled by default) + ///
+ /// 启用/禁用到配对端口方向的波特率仿真(默认禁用) + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder EmulateBaudRate(bool enable) + { + return WithArgument("EmuBR", enable ? "yes" : "no"); + } + + /// + /// Enable/disable buffer overrun (disabled by default) + ///
+ /// 启用/禁用缓冲区溢出(默认禁用) + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder EmulateOverrun(bool enable) + { + return WithArgument("EmuOverrun", enable ? "yes" : "no"); + } + + /// + /// Enable/disable plug-in mode, the plug-in mode port is hidden and can't be open if the paired port is not open(disabled by default) + ///
+ /// 启用/禁用插件模式,插件模式端口是隐藏的,如果配对端口未打开则无法打开(默认禁用) + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder PlugInMode(bool enable) + { + return WithArgument("PlugInMode", enable ? "yes" : "no"); + } + + /// + /// Enable/disable exclusive mode, the exclusive mode port is hidden if it is open(disabled by default) + ///
+ /// 启用/禁用独占模式,独占模式端口如果打开则隐藏(默认禁用) + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + + public PortBuilder ExclusiveMode(bool enable) + { + return WithArgument("ExclusiveMode", enable ? "yes" : "no"); + } + + /// + /// Enable/disable hidden mode, the hidden mode port is hidden as it is possible for port enumerators (disabled by default) + /// 启用/禁用隐藏模式 + /// + /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder HiddenMode(bool enable) + { + return WithArgument("HiddenMode", enable ? "yes" : "no"); + } + + /// + /// Enable/disable all data bits transfer disregard + ///
+ /// 启用/禁用忽略所有数据位传输 + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder AllDataBits(bool enable) + { + return WithArgument("AllDataBits", enable ? "yes" : "no"); + } + + //public PortBuilder Cts(bool enable) + //{ + // return WithArgument("cts", enable ? "rrts" : "!rrts"); + //} + + //public PortBuilder Dsr(bool enable) + //{ + // return WithArgument("dsr", enable ? "rdtr" : "!rdtr"); + //} + + //public PortBuilder Dcd(bool enable) + //{ + // return WithArgument("dcd", enable ? "rdtr" : "!rdtr"); + //} + + /// + /// Ring indicator + ///
+ /// 振铃指示 + ///
+ /// + /// Enable or not + ///
+ /// 启用/禁用 + /// + /// + public PortBuilder RingIndicator(bool enable) + { + return WithArgument("ri", enable ? "on" : "!on"); + } + + /// + /// + /// + /// + /// + /// + private PortBuilder WithArgument(string key, string value) + { + _arguments.AddOrUpdate(key, value, (o, n) => value); + return this; + } + + /// + public override string ToString() + { + var builder = new StringBuilder(); + int i = 0; + var keys = _arguments.Keys.ToArray(); + builder.Append($"{keys[i]}={_arguments[keys[i]]}"); + + while (i < _arguments.Count - 1) + { + i++; + builder.Append($",{keys[i]}={_arguments[keys[i]]}"); + } + + return builder.ToString(); + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/PortBus.cs b/src/Hsu.NullModemEmulator/PortBus.cs new file mode 100644 index 0000000..48e1fb9 --- /dev/null +++ b/src/Hsu.NullModemEmulator/PortBus.cs @@ -0,0 +1,67 @@ +namespace Hsu.NullModemEmulator; + +/// +/// The pair ports bus +///
+/// 成对虚拟串口 +///
+public record PortBus +{ + /// + /// Identity of pair port + ///
+ /// 成对虚拟串口标识 + ///
+ public int Id { get; set; } + /// + /// Name:CNCBUS[n] + ///
+ /// 名称:CNCBUS[n] + ///
+ public string Name { get; set; } + /// + /// the first port of pair + ///
+ /// 第一个虚拟串口 + ///
+ public PortDescriptior A { get; set; } + /// + /// the second port of pair + ///
+ /// 第二个虚拟串口 + ///
+ public PortDescriptior B { get; set; } + + /// + /// + /// + /// + /// Identity of pair port + ///
+ /// 成对虚拟串口标识 + /// + public PortBus(int id) + { + Id = id; + Name = $"CNCBUS{id}"; + } + + /// + /// + /// + /// + /// the first port of pair + ///
+ /// 第一个虚拟串口 + /// + /// + /// the second port of pair + ///
+ /// 第二个虚拟串口 + /// + public PortBus(PortDescriptior a, PortDescriptior b) + { + A = a; + B = b; + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/PortBusDescriptior.cs b/src/Hsu.NullModemEmulator/PortBusDescriptior.cs new file mode 100644 index 0000000..50fc98a --- /dev/null +++ b/src/Hsu.NullModemEmulator/PortBusDescriptior.cs @@ -0,0 +1,47 @@ +namespace Hsu.NullModemEmulator; + +/// +/// The descriptior of virtual port bus +///
+/// 虚拟串口对描述符 +///
+public record PortBusDescriptior +{ + /// + /// Identity of virtual port bus + ///
+ /// 虚拟串口对标识 + ///
+ public int Id { get; set; } + /// + /// The descriptior friendly name of bus + ///
+ /// 虚拟串口对友好名称描述符 + ///
+ public FriendlyNameDescriptior Bus { get; set; } + /// + /// The descriptior friendly name of first virtual port + ///
+ /// A虚拟串口友好名称描述符 + ///
+ public FriendlyNameDescriptior A { get; set; } + /// + /// The descriptior friendly name of second virtual port + ///
+ /// B虚拟串口友好名称描述符 + ///
+ public FriendlyNameDescriptior B { get; set; } + + /// + /// Constructor + /// + /// + /// Identity of virtual port bus + ///
+ /// 虚拟串口对标识 + /// + public PortBusDescriptior(int id) + { + Id = id; + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/PortBusOrder.cs b/src/Hsu.NullModemEmulator/PortBusOrder.cs new file mode 100644 index 0000000..8cb7e24 --- /dev/null +++ b/src/Hsu.NullModemEmulator/PortBusOrder.cs @@ -0,0 +1,23 @@ +namespace Hsu.NullModemEmulator; + +/// +/// The order of bus +///
+/// 串口对顺序 +///
+public enum PortBusOrder +{ + /// + /// The first port + ///
+ /// 第一个串口 + ///
+ A, + + /// + /// The second port + ///
+ /// 第二个串口 + ///
+ B +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/PortDescriptior.cs b/src/Hsu.NullModemEmulator/PortDescriptior.cs new file mode 100644 index 0000000..73fb1f1 --- /dev/null +++ b/src/Hsu.NullModemEmulator/PortDescriptior.cs @@ -0,0 +1,147 @@ +using System.Runtime.Serialization; + +namespace Hsu.NullModemEmulator; + +/* +CNCA0 PortName=COM1, +EmuBR=no, +EmuOverrun=no|yes, +PlugInMode=no|yes, +ExclusiveMode=no|yes, +HiddenMode=no|yes, +AllDataBits=no|yes, +cts=rrts|!rrts, +dsr=rdtr|!rdtr, +dcd=rdtr|!rdtr, +ri=!on|on, +EmuNoise=0, +AddRTTO=0, +AddRITO=0 + +*/ +/// +/// The descriptior of virtual port +///
+/// 虚拟串口描述符 +///
+public record PortDescriptior +{ + /// + /// Pair identity + ///
+ /// 虚拟串口对总线标识 + ///
+ public int BusId { get; set; } + /// + /// The order of port + ///
+ /// 虚拟串口顺序 + ///
+ public PortBusOrder BusOrder { get; set; } + /// + /// Device name,the actual name of the virtual serial port + ///
+ /// 设备名称,虚拟串口实际名称 + ///
+ public string DeviceName { get; set; } + /// + /// Port Name + ///
+ /// 串口名称 + ///
+ [DataMember(Name = "PortName")] + public string PortName { get; set; } + /// + /// Enable/disable baud rate emulation in the direction to the paired port(disabled by default) + ///
+ /// 启用/禁用到配对端口方向的波特率仿真(默认禁用) + ///
+ [DataMember(Name = "EmuBR")] + public bool EmulateBaudRate { get; set; } + /// + /// Enable/disable buffer overrun (disabled by default) + ///
+ /// 启用/禁用缓冲区溢出(默认禁用) + ///
+ [DataMember(Name = "EmuOverrun")] + public bool EmulateOverrun { get; set; } + /// + /// Enable/disable plug-in mode, the plug-in mode port is hidden and can't be open if the paired port is not open(disabled by default) + ///
+ /// 启用/禁用插件模式,插件模式端口是隐藏的,如果配对端口未打开则无法打开(默认禁用) + ///
+ [DataMember(Name = "PlugInMode")] + public bool PlugInMode { get; set; } + /// + /// Enable/disable exclusive mode, the exclusive mode port is hidden if it is open(disabled by default) + ///
+ /// 启用/禁用独占模式,独占模式端口如果打开则隐藏(默认禁用) + ///
+ [DataMember(Name = "ExclusiveMode")] + public bool ExclusiveMode { get; set; } + /// + /// Enable/disable hidden mode, the hidden mode port is hidden as it is possible for port enumerators (disabled by default) + /// 启用/禁用隐藏模式 + /// + [DataMember(Name = "HiddenMode")] + public bool HideMode { get; set; } + /// + /// Enable/disable all data bits transfer disregard + ///
+ /// 启用/禁用忽略所有数据位传输 + ///
+ [DataMember(Name = "AllDataBits")] + public bool AllDataBits { get; set; } + /// + /// Clear to Send + ///
+ /// 清除发送 + ///
+ [DataMember(Name = "cts")] + public bool Cts { get; set; } + /// + /// Data set Ready + ///
+ /// 数据准备好 + ///
+ [DataMember(Name = "dsr")] + public bool Dsr { get; set; } + /// + /// Data Carrier Detect + ///
+ /// 数据载波检测 + ///
+ [DataMember(Name = "dcd")] + public bool Dcd { get; set; } + /// + /// Ring indicator + ///
+ /// 振铃指示 + ///
+ [DataMember(Name = "ri")] + public bool RingIndicator { get; set; } + + /// + /// Emulate Noise:Probability in range 0-0.99999999 of error per character frame in the direction to the paired port(0 by default) + ///
+ /// 模拟噪声:到配对端口的方向上每个字符帧的错误概率在 0-0.99999999 范围内(默认为 0) + ///
+ [DataMember(Name = "EmuNoise")] + public float EmulateNoise { get; set; } + + /// + /// add [n] milliseconds to the total time-out period for read operations(0 by default) + ///
+ /// 将 [n] 毫秒添加到读取操作的总超时时间(默认为 0) + ///
+ [DataMember(Name = "AddRTTO")] + public int AddRTTO { get; set; } = 0; + + /// + /// add [n] milliseconds to the maximum time allowed to elapse between the arrival of two characters for read operations(0 by default) + ///
+ /// 将 [n] 毫秒添加到两个字符到达读取操作之间允许经过的最长时间(默认为 0) + ///
+ [DataMember(Name = "AddRITO")] + public int AddRITO { get; set; } = 0; +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/RegistryHelper.cs b/src/Hsu.NullModemEmulator/RegistryHelper.cs new file mode 100644 index 0000000..7d8dee3 --- /dev/null +++ b/src/Hsu.NullModemEmulator/RegistryHelper.cs @@ -0,0 +1,22 @@ +using Microsoft.Win32; + +namespace Hsu.NullModemEmulator; + +internal class RegistryHelper +{ + private const string NullModemEmulatorName = "com0com"; + private const string REGISTRY_KEY = $@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{NullModemEmulatorName}"; + private const string REGISTRY_KEY_32 = $@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{NullModemEmulatorName}"; + + private static string GetInstallPath(string key) + { + using RegistryKey com = Registry.LocalMachine.OpenSubKey(key); + if (com == null) return null; + return com.GetValue("InstallLocation")?.ToString(); + } + + public static string GetInstallPath() + { + return GetInstallPath(REGISTRY_KEY) ?? GetInstallPath(REGISTRY_KEY_32); + } +} \ No newline at end of file diff --git a/src/Hsu.NullModemEmulator/help.txt b/src/Hsu.NullModemEmulator/help.txt new file mode 100644 index 0000000..f96e851 --- /dev/null +++ b/src/Hsu.NullModemEmulator/help.txt @@ -0,0 +1,107 @@ +Setup for com0com + +Usage: + C:\Program Files (x86)\com0com\setupc.exe [options] + +Options: + --output - file for output, default is console + --wait [+] - wait seconds for install completion. If + has '+' prefix then ask user to continue + waiting after seconds elapsing + (by default is 0 - no wait) + --detail-prms - show detailed parameters + --silent - suppress dialogs if possible + --no-update - do not update driver while install command + execution (the other install command w/o this + option expected later) + --no-update-fnames - do not update friendly names + --show-fnames - show friendly names activity + +Commands: + install - install a pair of linked ports with + or identifiers CNCA and CNCB + install (by default is the first not used number), + set their parameters to and + install - can be used to update driver after execution + of install commands with --no-update option + remove - remove a pair of linked ports with + identifiers CNCA and CNCB + disable all - disable all ports in current hardware profile + enable all - enable all ports in current hardware profile + change - set parameters for port with + identifier + list - for each port show its identifier and + parameters + preinstall - preinstall driver + update - update driver + reload - reload driver + uninstall - uninstall all ports and the driver + infclean - clean old INF files + busynames - show names that already in use and match the + (wildcards: '*' and '?') + updatefnames - update friendly names + listfnames - for each bus and port show its identifier and + friendly name + quit - quit + help - print this help + +Syntax of port parameters string: + - - use driver's defaults for all parameters + * - use current settings for all parameters + =[,...] - set value for each parameter + +Parameters: + PortName= - set port name to + (port identifier by default) + EmuBR={yes|no} - enable/disable baud rate emulation in the direction + to the paired port (disabled by default) + EmuOverrun={yes|no} - enable/disable buffer overrun (disabled by default) + EmuNoise= - probability in range 0-0.99999999 of error per + character frame in the direction to the paired port + (0 by default) + AddRTTO= - add milliseconds to the total time-out period + for read operations (0 by default) + AddRITO= - add milliseconds to the maximum time allowed to + elapse between the arrival of two characters for + read operations (0 by default) + PlugInMode={yes|no} - enable/disable plug-in mode, the plug-in mode port + is hidden and can't be open if the paired port is + not open (disabled by default) + ExclusiveMode={yes|no} - enable/disable exclusive mode, the exclusive mode + port is hidden if it is open (disabled by default) + HiddenMode={yes|no} - enable/disable hidden mode, the hidden mode port is + hidden as it is possible for port enumerators + (disabled by default) + AllDataBits={yes|no} - enable/disable all data bits transfer disregard + data bits setting (disabled by default) + cts=[!]

- wire CTS pin to

(rrts by default) + dsr=[!]

- wire DSR pin to

(rdtr by default) + dcd=[!]

- wire DCD pin to

(rdtr by default) + ri=[!]

- wire RI pin to

(!on by default) + +The possible values of

above can be rrts, lrts, rdtr, ldtr, rout1, lout1, +rout2, lout2 (remote/local RTS/DTR/OUT1/OUT2), ropen, lopen (logical ON if +remote/local port is open) or on (logical ON). The exclamation sign (!) can be +used to invert the value. + +Special values: + - - use driver's default value + * - use current setting + +If parameter 'PortName=COM#' is used then the Ports class installer will be +invoked to set the real port name. The Ports class installer selects the COM +port number and sets the real port name to COM, where is the selected +port number. Thereafter use parameter RealPortName=COM to change the real +port name. + +Examples: + C:\Program Files (x86)\com0com\setupc.exe install - - + C:\Program Files (x86)\com0com\setupc.exe install 5 * * + C:\Program Files (x86)\com0com\setupc.exe remove 0 + C:\Program Files (x86)\com0com\setupc.exe install PortName=COM2 PortName=COM4 + C:\Program Files (x86)\com0com\setupc.exe install PortName=COM5,EmuBR=yes,EmuOverrun=yes - + C:\Program Files (x86)\com0com\setupc.exe change CNCA0 EmuBR=yes,EmuOverrun=yes + C:\Program Files (x86)\com0com\setupc.exe change CNCA0 PortName=- + C:\Program Files (x86)\com0com\setupc.exe list + C:\Program Files (x86)\com0com\setupc.exe uninstall + C:\Program Files (x86)\com0com\setupc.exe busynames COM?* \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..7663143 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1310 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.5.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + dependencies: + mimic-response "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +connect-livereload@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/connect-livereload/-/connect-livereload-0.6.1.tgz#1ac0c8bb9d9cfd5b28b629987a56a9239db9baaa" + integrity sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g== + +connect@^3.6.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +cp-file@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" + integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +docsify-cli@^4.4.4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/docsify-cli/-/docsify-cli-4.4.4.tgz#a9016d59545ec100b46955a72b127e78a888e55d" + integrity sha512-NAZgg6b0BsDuq/Pe+P19Qb2J1d+ZVbS0eGkeCNxyu4F9/CQSsRqZqAvPJ9/0I+BCHn4sgftA2jluqhQVzKzrSA== + dependencies: + chalk "^2.4.2" + connect "^3.6.0" + connect-history-api-fallback "^1.6.0" + connect-livereload "^0.6.0" + cp-file "^7.0.0" + docsify "^4.12.2" + docsify-server-renderer ">=4.10.0" + enquirer "^2.3.6" + fs-extra "^8.1.0" + get-port "^5.0.0" + livereload "^0.9.2" + lru-cache "^5.1.1" + open "^6.4.0" + serve-static "^1.12.1" + update-notifier "^4.1.0" + yargonaut "^1.1.2" + yargs "^15.3.0" + +docsify-server-renderer@>=4.10.0: + version "4.12.2" + resolved "https://registry.yarnpkg.com/docsify-server-renderer/-/docsify-server-renderer-4.12.2.tgz#c59d9110536f006141957ae71de334c687b83bfd" + integrity sha512-/sCq0U0iGvc8mNN6VC5SeodiHUsA98rMsMFYXtQbWsS/jWArkSee8ATlH5KzGDJ/zjf9QOFrkjoanHCNaFWiPQ== + dependencies: + debug "^4.3.3" + docsify "^4.12.1" + dompurify "^2.3.2" + node-fetch "^2.6.6" + resolve-pathname "^3.0.0" + +docsify@^4.12.1, docsify@^4.12.2: + version "4.12.2" + resolved "https://registry.yarnpkg.com/docsify/-/docsify-4.12.2.tgz#749115d2ff7d358780ea865e01f4a0162423d67f" + integrity sha512-hpRez5upcvkYigT2zD8P5kH5t9HpSWL8yn/ZU/g04/WfAfxVNW6CPUVOOF1EsQUDxTRuyNTFOb6uUv+tPij3tg== + dependencies: + dompurify "^2.3.1" + marked "^1.2.9" + medium-zoom "^1.0.6" + opencollective-postinstall "^2.0.2" + prismjs "^1.23.0" + strip-indent "^3.0.0" + tinydate "^1.3.0" + tweezer.js "^1.4.0" + +dompurify@^2.3.1, dompurify@^2.3.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f" + integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw== + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +figlet@^1.1.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.5.2.tgz#dda34ff233c9a48e36fcff6741aeb5bafe49b634" + integrity sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + 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" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-port@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +global-dirs@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" + integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== + dependencies: + ini "1.3.7" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +livereload-js@^3.3.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.4.0.tgz#2083158125f16fb5207141bbadb9bdc26cfdb1ef" + integrity sha512-F/pz9ZZP+R+arY94cECTZco7PXgBXyL+KVWUPZq8AQE9TOu14GV6fYeKOviv02JCvFa4Oi3Rs1hYEpfeajc+ow== + +livereload@^0.9.2: + version "0.9.3" + resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.3.tgz#a714816375ed52471408bede8b49b2ee6a0c55b1" + integrity sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw== + dependencies: + chokidar "^3.5.0" + livereload-js "^3.3.1" + opts ">= 1.2.0" + ws "^7.4.3" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +marked@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.9.tgz#53786f8b05d4c01a2a5a76b7d1ec9943d29d72dc" + integrity sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw== + +medium-zoom@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/medium-zoom/-/medium-zoom-1.0.6.tgz#9247f21ca9313d8bbe9420aca153a410df08d027" + integrity sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg== + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimist@^1.2.0: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nested-error-stacks@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" + integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== + +node-fetch@^2.6.6: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +open@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== + dependencies: + is-wsl "^1.1.0" + +opencollective-postinstall@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" + integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== + +"opts@>= 1.2.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1" + integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-event@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +parent-require@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-require/-/parent-require-1.0.0.tgz#746a167638083a860b0eef6732cb27ed46c32977" + integrity sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + +prismjs@^1.23.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pupa@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@^1.12.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + +tinydate@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tinydate/-/tinydate-1.3.0.tgz#e6ca8e5a22b51bb4ea1c3a2a4fd1352dbd4c57fb" + integrity sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w== + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tweezer.js@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/tweezer.js/-/tweezer.js-1.5.0.tgz#ca50ac5215022203fd3be4d28617e8e2305f5c0c" + integrity sha512-aSiJz7rGWNAQq7hjMK9ZYDuEawXupcCWgl3woQQSoDP2Oh8O4srWb/uO1PzzHIsrPEOqrjJ2sUb9FERfzuBabQ== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-notifier@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.3: + version "7.5.8" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a" + integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargonaut@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c" + integrity sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA== + dependencies: + chalk "^1.1.1" + figlet "^1.1.1" + parent-require "^1.0.0" + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.3.0: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2"