diff --git a/.editorconfig b/.editorconfig
index 128b6f1712..9ae52b8bbd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -134,6 +134,20 @@ csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
space_within_single_line_array_initializer_braces = true
+#Net Analyzer
+dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
+
+# CA1802: Use literals where appropriate
+dotnet_diagnostic.CA1802.severity = warning
+# CA1820: Test for empty strings using string length
+dotnet_diagnostic.CA1820.severity = warning
+# CA1821: Remove empty finalizers
+dotnet_diagnostic.CA1821.severity = warning
+# CA1825: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = warning
+#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
+dotnet_diagnostic.CA1847.severity = warning
+
# Wrapping preferences
csharp_wrap_before_ternary_opsigns = false
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index c5a719ce90..df070c35cf 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1 +1,2 @@
+github: avaloniaui
open_collective: avalonia
diff --git a/.gitignore b/.gitignore
index 61a3b53de1..bbf358b8f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -210,9 +210,9 @@ coc-settings.json
.ccls-cache
.ccls
*.map
-src/Web/Avalonia.Web.Blazor/wwwroot/*.js
-src/Web/Avalonia.Web.Blazor/Interop/Typescript/*.js
+src/Browser/Avalonia.Browser.Blazor/wwwroot/*.js
+src/Browser/Avalonia.Browser.Blazor/Interop/Typescript/*.js
node_modules
-src/Web/Avalonia.Web.Blazor/webapp/package-lock.json
-src/Web/Avalonia.Web.Blazor/wwwroot
-src/Web/Avalonia.Web/wwwroot
+src/Browser/Avalonia.Browser.Blazor/webapp/package-lock.json
+src/Browser/Avalonia.Browser.Blazor/wwwroot
+src/Browser/Avalonia.Browser/wwwroot
diff --git a/.ncrunch/Avalonia.Web.Blazor.v3.ncrunchproject b/.ncrunch/Avalonia.Web.Blazor.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Web.Blazor.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Web.v3.ncrunchproject b/.ncrunch/Avalonia.Web.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Web.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Win32.net6.0.v3.ncrunchproject b/.ncrunch/Avalonia.Win32.net6.0.v3.ncrunchproject
index 28b692bb51..95a483b433 100644
--- a/.ncrunch/Avalonia.Win32.net6.0.v3.ncrunchproject
+++ b/.ncrunch/Avalonia.Win32.net6.0.v3.ncrunchproject
@@ -1,7 +1,3 @@
-
-
- ..\..\tools\MicroComGenerator\bin\Debug\net6.0\**.*
-
-
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Win32.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Win32.netstandard2.0.v3.ncrunchproject
index 28b692bb51..95a483b433 100644
--- a/.ncrunch/Avalonia.Win32.netstandard2.0.v3.ncrunchproject
+++ b/.ncrunch/Avalonia.Win32.netstandard2.0.v3.ncrunchproject
@@ -1,7 +1,3 @@
-
-
- ..\..\tools\MicroComGenerator\bin\Debug\net6.0\**.*
-
-
+
\ No newline at end of file
diff --git a/.ncrunch/ControlCatalog.Blazor.Web.v3.ncrunchproject b/.ncrunch/ControlCatalog.Blazor.Web.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/ControlCatalog.Blazor.Web.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.Android.v3.ncrunchproject b/.ncrunch/MobileSandbox.Android.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.Android.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.Desktop.v3.ncrunchproject b/.ncrunch/MobileSandbox.Desktop.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.Desktop.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.iOS.v3.ncrunchproject b/.ncrunch/MobileSandbox.iOS.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.iOS.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.net6.0.v3.ncrunchproject b/.ncrunch/MobileSandbox.net6.0.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.net6.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.netstandard2.0.v3.ncrunchproject b/.ncrunch/MobileSandbox.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/_build.v3.ncrunchproject b/.ncrunch/_build.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/_build.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
new file mode 100644
index 0000000000..6ba05332be
--- /dev/null
+++ b/Avalonia.Desktop.slnf
@@ -0,0 +1,60 @@
+{
+ "solution": {
+ "path": "Avalonia.sln",
+ "projects": [
+ "packages\\Avalonia\\Avalonia.csproj",
+ "samples\\ControlCatalog.NetCore\\ControlCatalog.NetCore.csproj",
+ "samples\\ControlCatalog\\ControlCatalog.csproj",
+ "samples\\IntegrationTestApp\\IntegrationTestApp.csproj",
+ "samples\\MiniMvvm\\MiniMvvm.csproj",
+ "samples\\SampleControls\\ControlSamples.csproj",
+ "samples\\Sandbox\\Sandbox.csproj",
+ "src\\Avalonia.Base\\Avalonia.Base.csproj",
+ "src\\Avalonia.Build.Tasks\\Avalonia.Build.Tasks.csproj",
+ "src\\Avalonia.Controls.ColorPicker\\Avalonia.Controls.ColorPicker.csproj",
+ "src\\Avalonia.Controls.DataGrid\\Avalonia.Controls.DataGrid.csproj",
+ "src\\Avalonia.Controls\\Avalonia.Controls.csproj",
+ "src\\Avalonia.DesignerSupport\\Avalonia.DesignerSupport.csproj",
+ "src\\Avalonia.Desktop\\Avalonia.Desktop.csproj",
+ "src\\Avalonia.Diagnostics\\Avalonia.Diagnostics.csproj",
+ "src\\Avalonia.Dialogs\\Avalonia.Dialogs.csproj",
+ "src\\Avalonia.FreeDesktop\\Avalonia.FreeDesktop.csproj",
+ "src\\Avalonia.Headless.Vnc\\Avalonia.Headless.Vnc.csproj",
+ "src\\Avalonia.Headless\\Avalonia.Headless.csproj",
+ "src\\Avalonia.MicroCom\\Avalonia.MicroCom.csproj",
+ "src\\Avalonia.Native\\Avalonia.Native.csproj",
+ "src\\Avalonia.OpenGL\\Avalonia.OpenGL.csproj",
+ "src\\Avalonia.ReactiveUI\\Avalonia.ReactiveUI.csproj",
+ "src\\Avalonia.Remote.Protocol\\Avalonia.Remote.Protocol.csproj",
+ "src\\Avalonia.Themes.Fluent\\Avalonia.Themes.Fluent.csproj",
+ "src\\Avalonia.Themes.Simple\\Avalonia.Themes.Simple.csproj",
+ "src\\Avalonia.X11\\Avalonia.X11.csproj",
+ "src\\Linux\\Avalonia.LinuxFramebuffer\\Avalonia.LinuxFramebuffer.csproj",
+ "src\\Markup\\Avalonia.Markup.Xaml.Loader\\Avalonia.Markup.Xaml.Loader.csproj",
+ "src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
+ "src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj",
+ "src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj",
+ "src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj",
+ "src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj",
+ "src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
+ "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
+ "src\\tools\\DevGenerators\\DevGenerators.csproj",
+ "tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
+ "tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
+ "tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
+ "tests\\Avalonia.Controls.UnitTests\\Avalonia.Controls.UnitTests.csproj",
+ "tests\\Avalonia.DesignerSupport.TestApp\\Avalonia.DesignerSupport.TestApp.csproj",
+ "tests\\Avalonia.DesignerSupport.Tests\\Avalonia.DesignerSupport.Tests.csproj",
+ "tests\\Avalonia.Direct2D1.RenderTests\\Avalonia.Direct2D1.RenderTests.csproj",
+ "tests\\Avalonia.Direct2D1.UnitTests\\Avalonia.Direct2D1.UnitTests.csproj",
+ "tests\\Avalonia.IntegrationTests.Appium\\Avalonia.IntegrationTests.Appium.csproj",
+ "tests\\Avalonia.LeakTests\\Avalonia.LeakTests.csproj",
+ "tests\\Avalonia.Markup.UnitTests\\Avalonia.Markup.UnitTests.csproj",
+ "tests\\Avalonia.Markup.Xaml.UnitTests\\Avalonia.Markup.Xaml.UnitTests.csproj",
+ "tests\\Avalonia.ReactiveUI.UnitTests\\Avalonia.ReactiveUI.UnitTests.csproj",
+ "tests\\Avalonia.Skia.RenderTests\\Avalonia.Skia.RenderTests.csproj",
+ "tests\\Avalonia.Skia.UnitTests\\Avalonia.Skia.UnitTests.csproj",
+ "tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 81a9b43890..34b5596119 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -41,6 +41,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
+ src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs = src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
@@ -90,6 +91,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
build\ApiDiff.props = build\ApiDiff.props
+ build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
build\CoreLibraries.props = build\CoreLibraries.props
@@ -102,8 +104,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props
+ build\NetAnalyzers.props = build\NetAnalyzers.props
build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
+ build\NullableEnable.props = build\NullableEnable.props
build\ReactiveUI.props = build\ReactiveUI.props
build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props
build\Rx.props = build\Rx.props
@@ -194,11 +198,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTestApp", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.IntegrationTests.Appium", "tests\Avalonia.IntegrationTests.Appium\Avalonia.IntegrationTests.Appium.csproj", "{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Blazor", "src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj", "{25831348-EB2A-483E-9576-E8F6528674A5}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Web", "samples\ControlCatalog.Web\ControlCatalog.Web.csproj", "{C08E9894-AA92-426E-BF56-033E262CAD3E}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Browser", "Browser", "{86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{26A98DA1-D89D-4A95-8152-349F404DA2E2}"
EndProject
@@ -214,17 +214,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevGenerators", "src\tools\DevGenerators\DevGenerators.csproj", "{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web", "src\Web\Avalonia.Web\Avalonia.Web.csproj", "{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Sample", "src\Web\Avalonia.Web.Sample\Avalonia.Web.Sample.csproj", "{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser.Blazor", "samples\ControlCatalog.Browser.Blazor\ControlCatalog.Browser.Blazor.csproj", "{90B08091-9BBD-4362-B712-E9F2CC62B218}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -476,14 +480,6 @@ Global
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.Build.0 = Release|Any CPU
- {25831348-EB2A-483E-9576-E8F6528674A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {25831348-EB2A-483E-9576-E8F6528674A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.Build.0 = Release|Any CPU
- {C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.Build.0 = Release|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -512,20 +508,13 @@ Global
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.Build.0 = Release|Any CPU
- {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.Build.0 = Release|Any CPU
- {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.Build.0 = Release|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Release|Any CPU.Build.0 = Release|Any CPU
{C90FE60B-B01E-4F35-91D6-379D6966030F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C90FE60B-B01E-4F35-91D6-379D6966030F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C90FE60B-B01E-4F35-91D6-379D6966030F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{C90FE60B-B01E-4F35-91D6-379D6966030F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C90FE60B-B01E-4F35-91D6-379D6966030F}.Release|Any CPU.Build.0 = Release|Any CPU
{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -536,6 +525,22 @@ Global
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4A39637C-9338-4925-A4DB-D072E292EC78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A39637C-9338-4925-A4DB-D072E292EC78}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.Build.0 = Release|Any CPU
+ {47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90B08091-9BBD-4362-B712-E9F2CC62B218}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90B08091-9BBD-4362-B712-E9F2CC62B218}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -579,27 +584,27 @@ Global
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+ {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
- {25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
- {C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{26A98DA1-D89D-4A95-8152-349F404DA2E2} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
- {76D39FF6-6B4F-46C4-93CD-E6FC4665739E} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
- {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
- {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C90FE60B-B01E-4F35-91D6-379D6966030F} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{62D392C9-81CF-487F-92E8-598B2AF3FDCE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {4A39637C-9338-4925-A4DB-D072E292EC78} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
+ {47F8530C-F19B-4B1A-B4D6-EB231522AE5D} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
+ {15B93A4C-1B46-43F6-B534-7B25B6E99932} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {90B08091-9BBD-4362-B712-E9F2CC62B218} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000000..73954c7f4d
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,5 @@
+
+
+ $(DefineConstants);NET7SDK
+
+
diff --git a/Documentation/build.md b/Documentation/build.md
index ddd38be887..fd6b26337c 100644
--- a/Documentation/build.md
+++ b/Documentation/build.md
@@ -1,8 +1,8 @@
# Windows
-Avalonia requires at least Visual Studio 2022 and dotnet 6 SDK 6.0.100 to build on all platforms.
+Avalonia requires at least Visual Studio 2022 and dotnet 7-rc2 SDK 7.0.100-rc.2 to build on all platforms.
-### Clone the Avalonia repository
+## Clone the Avalonia repository
```
git clone https://github.com/AvaloniaUI/Avalonia.git
@@ -10,15 +10,30 @@ cd Avalonia
git submodule update --init
```
-### Install the required version of the .NET Core SDK
+## Install the required version of the .NET Core SDK
Go to https://dotnet.microsoft.com/download/visual-studio-sdks and install the latest version of the .NET Core SDK compatible with Avalonia UI. Make sure to download the SDK (not just the "runtime") package. The version compatible is indicated within the [global.json](https://github.com/AvaloniaUI/Avalonia/blob/master/global.json) file. Note that Avalonia UI does not always use the latest version and is hardcoded to use the last version known to be compatible (SDK releases may break the builds from time-to-time).
-### Open in Visual Studio
+## Build and Run Avalonia
-Open the `Avalonia.sln` solution in Visual Studio 2022 or newer. The free Visual Studio Community edition works fine. Build and run the `Samples\ControlCatalog.Desktop` or `ControlCatalog.NetCore` project to see the sample application.
+```
+cd samples\ControlCatalog.NetCore
+dotnet restore
+dotnet run
+```
+
+## Opening in Visual Studio
-### Troubleshooting
+If you want to open Avalonia in Visual Studio you have two options:
+
+- Avalonia.sln: This contains the whole of Avalonia in including desktop, mobile and web. You must have a number of dotnet workloads installed in order to build everything in this solution
+- Avalonia.Desktop.slnf: This solution filter opens only the parts of Avalonia required to run on desktop. This requires no extra workloads to be installed.
+
+Avalonia requires Visual Studio 2022 or newer. The free Visual Studio Community edition works fine.
+
+Build and run `ControlCatalog.NetCore` project to see the sample application.
+
+### Visual Studio Troubleshooting
* **Error CS0006: Avalonia.DesktopRuntime.dll could not be found**
@@ -35,16 +50,15 @@ It's *not* possible to build the *whole* project on Linux/macOS. You can only bu
MonoDevelop, Xamarin Studio and Visual Studio for Mac aren't capable of properly opening our solution. You can use Rider (at least 2017.2 EAP) or VSCode instead. They will fail to load most of platform specific projects, but you don't need them to run on .NET Core.
-### Install the latest version of the .NET Core SDK
+## Install the latest version of the .NET Core SDK
Go to https://www.microsoft.com/net/core and follow the instructions for your OS. Make sure to download the SDK (not just the "runtime") package.
-### Additional requirements for macOS
+## Additional requirements for macOS
The build process needs [Xcode](https://developer.apple.com/xcode/) to build the native library. Following the install instructions at the [Xcode](https://developer.apple.com/xcode/) website to properly install.
-
-### Clone the Avalonia repository
+## Clone the Avalonia repository
```
git clone https://github.com/AvaloniaUI/Avalonia.git
@@ -52,7 +66,7 @@ cd Avalonia
git submodule update --init --recursive
```
-### Build native libraries (macOS only)
+## Build native libraries (macOS only)
On macOS it is necessary to build and manually install the respective native libraries using [Xcode](https://developer.apple.com/xcode/). Execute the build script in the root project with the `CompileNative` task. It will build the headers, build the libraries, and place them in the appropriate place to allow .NET to find them at compilation and run time.
@@ -60,7 +74,7 @@ On macOS it is necessary to build and manually install the respective native lib
./build.sh CompileNative
```
-### Build and Run Avalonia
+## Build and Run Avalonia
```
cd samples/ControlCatalog.NetCore
diff --git a/NOTICE.md b/NOTICE.md
index 92fd725957..e97fc654c9 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -111,7 +111,7 @@ DEALINGS IN THE SOFTWARE.
# Metsys.Bson
-Copyright (c) 2010, Karl Seguin - http://www.openmymind.net/
+Copyright (c) 2010, Karl Seguin - https://www.openmymind.net/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -302,4 +302,4 @@ https://github.com/chromium/chromium
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/azure-pipelines-integrationtests.yml b/azure-pipelines-integrationtests.yml
index ee8abb75c1..43253ac6be 100644
--- a/azure-pipelines-integrationtests.yml
+++ b/azure-pipelines-integrationtests.yml
@@ -12,6 +12,16 @@ jobs:
name: 'AvaloniaMacPool'
steps:
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 6.0.401'
+ inputs:
+ version: 6.0.401
+
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 7.0.100'
+ inputs:
+ version: 7.0.100
+
- script: system_profiler SPDisplaysDataType |grep Resolution
- script: |
@@ -22,7 +32,7 @@ jobs:
rm -rf $(osascript -e "POSIX path of (path to application id \"net.avaloniaui.avalonia.integrationtestapp\")")
pkill IntegrationTestApp
./samples/IntegrationTestApp/bundle.sh
- open -n ./samples/IntegrationTestApp/bin/Debug/net6.0/osx-arm64/publish/IntegrationTestApp.app
+ open -n ./samples/IntegrationTestApp/bin/Debug/net7.0/osx-arm64/publish/IntegrationTestApp.app
pkill IntegrationTestApp
- task: DotNetCoreCLI@2
@@ -45,6 +55,11 @@ jobs:
inputs:
version: 6.0.401
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core SDK 7.0.100'
+ inputs:
+ version: 7.0.100
+
- task: Windows Application Driver@0
inputs:
OperationType: 'Start'
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 33b2dc670a..a3bbc33418 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -35,9 +35,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
+ displayName: 'Use .NET Core SDK 7.0'
inputs:
- version: 7.0.100-rc.1.22431.12
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -72,9 +72,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
+ displayName: 'Use .NET Core SDK 7.0.100'
inputs:
- version: 7.0.100-rc.1.22431.12
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -143,9 +143,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
+ displayName: 'Use .NET Core SDK 7.0.100'
inputs:
- version: 7.0.100-rc.1.22431.12
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
diff --git a/build/BuildTargets.targets b/build/BuildTargets.targets
index a5543cd050..481dbf06b2 100644
--- a/build/BuildTargets.targets
+++ b/build/BuildTargets.targets
@@ -3,6 +3,7 @@
$(MSBuildThisFileDirectory)\..\src\Avalonia.Build.Tasks\bin\$(Configuration)\netstandard2.0\Avalonia.Build.Tasks.dll
true
true
+ true
diff --git a/build/NetAnalyzers.props b/build/NetAnalyzers.props
new file mode 100644
index 0000000000..dfca9ecf9e
--- /dev/null
+++ b/build/NetAnalyzers.props
@@ -0,0 +1,5 @@
+
+
+ true
+
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 1b60bb4df9..5838519596 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -8,7 +8,7 @@
https://github.com/AvaloniaUI/Avalonia/
true
CS1591
- latest
+ preview
MIT
Icon.png
Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly.
diff --git a/dirs.proj b/dirs.proj
index a2544ef951..f1eaae8a4a 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -9,21 +9,18 @@
-
-
-
-
-
-
-
+
+
+
+
-
+
diff --git a/global.json b/global.json
index 44d4e10dbf..a9318b212f 100644
--- a/global.json
+++ b/global.json
@@ -1,4 +1,8 @@
{
+ "sdk": {
+ "version": "7.0.100",
+ "rollForward": "latestFeature"
+ },
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
"MSBuild.Sdk.Extras": "3.0.22",
diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm
index ebd9f39d30..6611dcc73f 100644
--- a/native/Avalonia.Native/src/OSX/AvnWindow.mm
+++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm
@@ -171,9 +171,7 @@
_closed = false;
_isEnabled = true;
- [self backingScaleFactor];
[self setOpaque:NO];
- [self setBackgroundColor: [NSColor clearColor]];
_isExtended = false;
_isTransitioningToFullScreen = false;
@@ -385,7 +383,7 @@
return true;
}
--(void)resignKeyWindow
+-(void)windowDidResignKey:(NSNotification *)notification
{
if(_parent)
_parent->BaseEvents->Deactivated();
@@ -393,8 +391,6 @@
[self showAppMenuOnly];
[self invalidateShadow];
-
- [super resignKeyWindow];
}
- (void)windowDidMove:(NSNotification *_Nonnull)notification
diff --git a/native/Avalonia.Native/src/OSX/Screens.mm b/native/Avalonia.Native/src/OSX/Screens.mm
index b9c75ed742..83ab1bfd01 100644
--- a/native/Avalonia.Native/src/OSX/Screens.mm
+++ b/native/Avalonia.Native/src/OSX/Screens.mm
@@ -41,9 +41,9 @@ public:
ret->WorkingArea.X = [screen visibleFrame].origin.x;
ret->WorkingArea.Y = ConvertPointY(ToAvnPoint([screen visibleFrame].origin)).Y - ret->WorkingArea.Height;
- ret->PixelDensity = [screen backingScaleFactor];
+ ret->Scaling = [screen backingScaleFactor];
- ret->Primary = index == 0;
+ ret->IsPrimary = index == 0;
return S_OK;
}
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
index 2baf3b09b5..7fb002e54f 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
@@ -90,7 +90,7 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost **retOut) override;
- virtual HRESULT SetBlurEnabled(bool enable) override;
+ virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard *clipboard, IAvnDndResultCallback *cb,
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
index 77f53332cd..9946ad9b10 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
@@ -489,10 +489,11 @@ HRESULT WindowBaseImpl::CreateNativeControlHost(IAvnNativeControlHost **retOut)
return S_OK;
}
-HRESULT WindowBaseImpl::SetBlurEnabled(bool enable) {
+HRESULT WindowBaseImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
START_COM_CALL;
- [StandardContainer ShowBlur:enable];
+ [Window setBackgroundColor: (mode != Transparent ? [NSColor windowBackgroundColor] : [NSColor clearColor])];
+ [StandardContainer ShowBlur: mode == Blur];
return S_OK;
}
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm
index ddc50c26b6..2443965957 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm
@@ -63,7 +63,7 @@ HRESULT WindowImpl::Show(bool activate, bool isDialog) {
START_COM_CALL;
@autoreleasepool {
- _isDialog = isDialog;
+ _isDialog = isDialog || _parent != nullptr;
WindowBaseImpl::Show(activate, isDialog);
@@ -96,6 +96,8 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) {
auto cparent = dynamic_cast(parent);
_parent = cparent;
+
+ _isDialog = _parent != nullptr;
if(_parent != nullptr && Window != nullptr){
// If one tries to show a child window with a minimized parent window, then the parent window will be
diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm
index a15d0c9601..9cc9fc9523 100644
--- a/native/Avalonia.Native/src/OSX/app.mm
+++ b/native/Avalonia.Native/src/OSX/app.mm
@@ -95,11 +95,14 @@ ComPtr _events;
}
@end
-extern void InitializeAvnApp(IAvnApplicationEvents* events)
+extern void InitializeAvnApp(IAvnApplicationEvents* events, bool disableAppDelegate)
{
- NSApplication* app = [AvnApplication sharedApplication];
- id delegate = [[AvnAppDelegate alloc] initWithEvents:events];
- [app setDelegate:delegate];
+ if(!disableAppDelegate)
+ {
+ NSApplication* app = [AvnApplication sharedApplication];
+ id delegate = [[AvnAppDelegate alloc] initWithEvents:events];
+ [app setDelegate:delegate];
+ }
}
HRESULT AvnApplicationCommands::HideApp()
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index a90a235b9d..7ee7205776 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -32,7 +32,7 @@ extern void SetServicesMenu (IAvnMenu* menu);
extern IAvnMenu* GetAppMenu ();
extern NSMenuItem* GetAppMenuItem ();
-extern void InitializeAvnApp(IAvnApplicationEvents* events);
+extern void InitializeAvnApp(IAvnApplicationEvents* events, bool disableAppDelegate);
extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;
extern NSPoint ToNSPoint (AvnPoint p);
extern NSRect ToNSRect (AvnRect r);
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index 6ee86b21ae..c29d4108d0 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -3,6 +3,8 @@
#include "common.h"
static NSString* s_appTitle = @"Avalonia";
+static int disableSetProcessName = 0;
+static bool disableAppDelegate = false;
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -111,11 +113,17 @@ public:
@autoreleasepool
{
auto appTitle = [NSString stringWithUTF8String: utf8String];
-
- [[NSProcessInfo processInfo] setProcessName:appTitle];
-
-
- SetProcessName(appTitle);
+ if (disableSetProcessName == 0)
+ {
+ [[NSProcessInfo processInfo] setProcessName:appTitle];
+
+ SetProcessName(appTitle);
+ }
+ if (disableSetProcessName == 1)
+ {
+ auto rootMenu = [NSApp mainMenu];
+ [rootMenu setTitle:appTitle];
+ }
return S_OK;
}
@@ -133,6 +141,27 @@ public:
}
}
+ virtual HRESULT SetDisableSetProcessName(int disable) override
+ {
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ disableSetProcessName = disable;
+ return S_OK;
+ }
+ }
+
+ virtual HRESULT SetDisableAppDelegate(int disable) override
+ {
+ START_COM_CALL;
+
+ @autoreleasepool {
+ disableAppDelegate = disable;
+ return S_OK;
+ }
+ }
+
};
/// See "Using POSIX Threads in a Cocoa Application" section here:
@@ -175,7 +204,7 @@ public:
@autoreleasepool{
[[ThreadingInitializer new] do];
}
- InitializeAvnApp(events);
+ InitializeAvnApp(events, disableAppDelegate);
return S_OK;
};
diff --git a/native/Avalonia.Native/src/OSX/menu.h b/native/Avalonia.Native/src/OSX/menu.h
index ce46ac11e0..405938318c 100644
--- a/native/Avalonia.Native/src/OSX/menu.h
+++ b/native/Avalonia.Native/src/OSX/menu.h
@@ -59,11 +59,20 @@ public:
void RaiseOnClicked();
};
+class AvnAppMenu;
+
+@interface AvnMenuDelegate : NSObject
+- (id) initWithParent: (AvnAppMenu*) parent;
+- (void) parentDestroyed;
+@end
+
+
class AvnAppMenu : public ComSingleObject
{
private:
AvnMenu* _native;
ComPtr _baseEvents;
+ AvnMenuDelegate* _delegate;
public:
FORWARD_IUNKNOWN()
@@ -83,12 +92,10 @@ public:
virtual HRESULT SetTitle (char* utf8String) override;
virtual HRESULT Clear () override;
+ virtual ~AvnAppMenu() override;
};
-@interface AvnMenuDelegate : NSObject
-- (id) initWithParent: (AvnAppMenu*) parent;
-@end
#endif
diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm
index b05588a441..cd1871de21 100644
--- a/native/Avalonia.Native/src/OSX/menu.mm
+++ b/native/Avalonia.Native/src/OSX/menu.mm
@@ -292,8 +292,13 @@ void AvnAppMenuItem::RaiseOnClicked()
AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
{
_baseEvents = events;
- id del = [[AvnMenuDelegate alloc] initWithParent: this];
- _native = [[AvnMenu alloc] initWithDelegate: del];
+ _delegate = [[AvnMenuDelegate alloc] initWithParent: this];
+ _native = [[AvnMenu alloc] initWithDelegate: _delegate];
+}
+
+AvnAppMenu::~AvnAppMenu()
+{
+ [_delegate parentDestroyed];
}
@@ -394,7 +399,7 @@ HRESULT AvnAppMenu::Clear()
@implementation AvnMenuDelegate
{
- ComPtr _parent;
+ AvnAppMenu* _parent;
}
- (id) initWithParent:(AvnAppMenu *)parent
{
@@ -402,6 +407,12 @@ HRESULT AvnAppMenu::Clear()
_parent = parent;
return self;
}
+
+- (void) parentDestroyed
+{
+ _parent = nullptr;
+}
+
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
if(shouldCancel)
@@ -416,17 +427,20 @@ HRESULT AvnAppMenu::Clear()
- (void)menuNeedsUpdate:(NSMenu *)menu
{
- _parent->RaiseNeedsUpdate();
+ if(_parent)
+ _parent->RaiseNeedsUpdate();
}
- (void)menuWillOpen:(NSMenu *)menu
{
- _parent->RaiseOpening();
+ if(_parent)
+ _parent->RaiseOpening();
}
- (void)menuDidClose:(NSMenu *)menu
{
- _parent->RaiseClosed();
+ if(_parent)
+ _parent->RaiseClosed();
}
@end
diff --git a/native/Avalonia.Native/src/OSX/rendertarget.mm b/native/Avalonia.Native/src/OSX/rendertarget.mm
index 2075cc85ab..1c22c91207 100644
--- a/native/Avalonia.Native/src/OSX/rendertarget.mm
+++ b/native/Avalonia.Native/src/OSX/rendertarget.mm
@@ -183,8 +183,11 @@ static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* ta
[_layer setContents: (__bridge IOSurface*) surface->surface];
}
[CATransaction commit];
- [CATransaction flush];
}
+ // This can trigger event processing on the main thread
+ // which might need to lock the renderer
+ // which can cause a deadlock. So flush call is outside of the lock
+ [CATransaction flush];
}
else
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 7425c344c3..2295c0beda 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -145,8 +145,25 @@ partial class Build : NukeBuild
{
Information($"Running tests from {projectName}");
var project = Solution.GetProject(projectName).NotNull("project != null");
+ // Nuke and MSBuild tools have build-in helpers to get target frameworks from the project.
+ // Unfortunately, it gets broken with every second SDK update, so we had to do it manually.
+ var fileXml = XDocument.Parse(File.ReadAllText(project.Path));
+ var targetFrameworks = fileXml.Descendants("TargetFrameworks")
+ .FirstOrDefault()?.Value.Split(';').Select(f => f.Trim());
+ if (targetFrameworks is null)
+ {
+ var targetFramework = fileXml.Descendants("TargetFramework").FirstOrDefault()?.Value;
+ if (targetFramework is not null)
+ {
+ targetFrameworks = new[] { targetFramework };
+ }
+ }
+ if (targetFrameworks is null)
+ {
+ throw new InvalidOperationException("No target frameworks were found in the test project");
+ }
- foreach (var fw in project.GetTargetFrameworks())
+ foreach (var fw in targetFrameworks)
{
if (fw.StartsWith("net4")
&& RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index 8c0d824298..92d9732e91 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -13,11 +13,11 @@
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index d43a5c1624..4f9c4d7720 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -3,8 +3,8 @@
<_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false
low
- <_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false
<_AvaloniaSkipXamlCompilation Condition="'$(_AvaloniaSkipXamlCompilation)' == ''">false
+ false
@@ -44,7 +44,7 @@
$(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences;_GenerateAvaloniaResourcesDependencyCache
-
+
@@ -71,7 +71,6 @@
Output="$(AvaloniaResourcesTemporaryFilePath)"
Root="$(MSBuildProjectDirectory)"
Resources="@(AvaloniaResource)"
- EmbeddedResources="@(EmbeddedResources)"
ReportImportance="$(AvaloniaXamlReportImportance)"/>
-
+
diff --git a/samples/BindingDemo/TestItemView.xaml b/samples/BindingDemo/TestItemView.xaml
index 46c34c6507..6edade34b2 100644
--- a/samples/BindingDemo/TestItemView.xaml
+++ b/samples/BindingDemo/TestItemView.xaml
@@ -1,8 +1,10 @@
+ xmlns:viewModels="using:BindingDemo.ViewModels"
+ x:Class="BindingDemo.TestItemView"
+ x:DataType="viewModels:TestItem">
-
\ No newline at end of file
+
diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs
index 33ca511340..62c582610c 100644
--- a/samples/ControlCatalog.Android/MainActivity.cs
+++ b/samples/ControlCatalog.Android/MainActivity.cs
@@ -5,16 +5,8 @@ using Avalonia.Android;
namespace ControlCatalog.Android
{
- [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
- public class MainActivity : AvaloniaActivity
+ [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+ public class MainActivity : AvaloniaMainActivity
{
- protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
- {
- return base.CustomizeAppBuilder(builder)
- .AfterSetup(_ =>
- {
- Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
- });
- }
}
}
diff --git a/samples/ControlCatalog.Android/SplashActivity.cs b/samples/ControlCatalog.Android/SplashActivity.cs
index dc292fd37b..908b5f082a 100644
--- a/samples/ControlCatalog.Android/SplashActivity.cs
+++ b/samples/ControlCatalog.Android/SplashActivity.cs
@@ -1,12 +1,23 @@
using Android.App;
using Android.Content;
+using Android.Content.PM;
using Android.OS;
+using Avalonia.Android;
namespace ControlCatalog.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
- public class SplashActivity : Activity
+ public class SplashActivity : AvaloniaSplashActivity
{
+ protected override Avalonia.AppBuilder CustomizeAppBuilder(Avalonia.AppBuilder builder)
+ {
+ return base.CustomizeAppBuilder(builder)
+ .AfterSetup(_ =>
+ {
+ Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
+ });
+ }
+
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
diff --git a/samples/ControlCatalog.Web/App.razor b/samples/ControlCatalog.Browser.Blazor/App.razor
similarity index 100%
rename from samples/ControlCatalog.Web/App.razor
rename to samples/ControlCatalog.Browser.Blazor/App.razor
diff --git a/samples/ControlCatalog.Browser.Blazor/App.razor.cs b/samples/ControlCatalog.Browser.Blazor/App.razor.cs
new file mode 100644
index 0000000000..f38db2b055
--- /dev/null
+++ b/samples/ControlCatalog.Browser.Blazor/App.razor.cs
@@ -0,0 +1,17 @@
+using Avalonia;
+using Avalonia.Browser.Blazor;
+
+namespace ControlCatalog.Browser.Blazor;
+
+public partial class App
+{
+ protected override void OnParametersSet()
+ {
+ AppBuilder.Configure()
+ .UseBlazor()
+ // .With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
+ .SetupWithSingleViewLifetime();
+
+ base.OnParametersSet();
+ }
+}
diff --git a/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj b/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
new file mode 100644
index 0000000000..d0fb614840
--- /dev/null
+++ b/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
@@ -0,0 +1,29 @@
+
+
+ net7.0
+ browser-wasm
+ enable
+ 16777216
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog.Web/Pages/Index.razor b/samples/ControlCatalog.Browser.Blazor/Pages/Index.razor
similarity index 50%
rename from samples/ControlCatalog.Web/Pages/Index.razor
rename to samples/ControlCatalog.Browser.Blazor/Pages/Index.razor
index 93ca07f9f1..7480e4c5e9 100644
--- a/samples/ControlCatalog.Web/Pages/Index.razor
+++ b/samples/ControlCatalog.Browser.Blazor/Pages/Index.razor
@@ -1,5 +1,5 @@
@page "/"
-@using Avalonia.Web.Blazor
+@using Avalonia.Browser.Blazor
diff --git a/samples/ControlCatalog.Web/Program.cs b/samples/ControlCatalog.Browser.Blazor/Program.cs
similarity index 94%
rename from samples/ControlCatalog.Web/Program.cs
rename to samples/ControlCatalog.Browser.Blazor/Program.cs
index d1a7925813..eb99ca518e 100644
--- a/samples/ControlCatalog.Web/Program.cs
+++ b/samples/ControlCatalog.Browser.Blazor/Program.cs
@@ -3,7 +3,7 @@ using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
-using ControlCatalog.Web;
+using ControlCatalog.Browser.Blazor;
public class Program
{
diff --git a/samples/ControlCatalog.Web/Properties/launchSettings.json b/samples/ControlCatalog.Browser.Blazor/Properties/launchSettings.json
similarity index 66%
rename from samples/ControlCatalog.Web/Properties/launchSettings.json
rename to samples/ControlCatalog.Browser.Blazor/Properties/launchSettings.json
index e4da60f7ca..ad2b1e30f6 100644
--- a/samples/ControlCatalog.Web/Properties/launchSettings.json
+++ b/samples/ControlCatalog.Browser.Blazor/Properties/launchSettings.json
@@ -8,14 +8,6 @@
}
},
"profiles": {
- "ControlCatalog.Web - IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- },
"ControlCatalog.Web": {
"commandName": "Project",
"dotnetRunMessages": "true",
diff --git a/samples/ControlCatalog.Web/Shared/MainLayout.razor b/samples/ControlCatalog.Browser.Blazor/Shared/MainLayout.razor
similarity index 100%
rename from samples/ControlCatalog.Web/Shared/MainLayout.razor
rename to samples/ControlCatalog.Browser.Blazor/Shared/MainLayout.razor
diff --git a/samples/ControlCatalog.Web/_Imports.razor b/samples/ControlCatalog.Browser.Blazor/_Imports.razor
similarity index 85%
rename from samples/ControlCatalog.Web/_Imports.razor
rename to samples/ControlCatalog.Browser.Blazor/_Imports.razor
index 04c7a8690e..dc4f778352 100644
--- a/samples/ControlCatalog.Web/_Imports.razor
+++ b/samples/ControlCatalog.Browser.Blazor/_Imports.razor
@@ -6,6 +6,5 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
-@using ControlCatalog.Web
-@using ControlCatalog.Web.Shared
+@using ControlCatalog.Browser.Blazor.Shared
@using SkiaSharp
diff --git a/samples/ControlCatalog.Web/wwwroot/css/app.css b/samples/ControlCatalog.Browser.Blazor/wwwroot/css/app.css
similarity index 100%
rename from samples/ControlCatalog.Web/wwwroot/css/app.css
rename to samples/ControlCatalog.Browser.Blazor/wwwroot/css/app.css
diff --git a/samples/ControlCatalog.Web/wwwroot/favicon.ico b/samples/ControlCatalog.Browser.Blazor/wwwroot/favicon.ico
similarity index 100%
rename from samples/ControlCatalog.Web/wwwroot/favicon.ico
rename to samples/ControlCatalog.Browser.Blazor/wwwroot/favicon.ico
diff --git a/samples/ControlCatalog.Web/wwwroot/index.html b/samples/ControlCatalog.Browser.Blazor/wwwroot/index.html
similarity index 100%
rename from samples/ControlCatalog.Web/wwwroot/index.html
rename to samples/ControlCatalog.Browser.Blazor/wwwroot/index.html
diff --git a/src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj b/samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj
similarity index 65%
rename from src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj
rename to samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj
index 13aad8c13e..c4278459f3 100644
--- a/src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj
+++ b/samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj
@@ -16,15 +16,18 @@
full
true
true
- true
- -O3
- -O3
+ -O2
+ -O2
-
-
-
+
+
+
+
+
+
+
@@ -36,6 +39,6 @@
-
-
+
+
diff --git a/src/Web/Avalonia.Web.Sample/EmbedSample.Browser.cs b/samples/ControlCatalog.Browser/EmbedSample.Browser.cs
similarity index 94%
rename from src/Web/Avalonia.Web.Sample/EmbedSample.Browser.cs
rename to samples/ControlCatalog.Browser/EmbedSample.Browser.cs
index 5baa4a6b35..c367230ddf 100644
--- a/src/Web/Avalonia.Web.Sample/EmbedSample.Browser.cs
+++ b/samples/ControlCatalog.Browser/EmbedSample.Browser.cs
@@ -1,13 +1,11 @@
using System;
using System.Runtime.InteropServices.JavaScript;
-
-using Avalonia;
using Avalonia.Platform;
-using Avalonia.Web;
+using Avalonia.Browser;
using ControlCatalog.Pages;
-namespace ControlCatalog.Web;
+namespace ControlCatalog.Browser;
public class EmbedSampleWeb : INativeDemoControl
{
diff --git a/src/Web/Avalonia.Web.Sample/Logo.svg b/samples/ControlCatalog.Browser/Logo.svg
similarity index 100%
rename from src/Web/Avalonia.Web.Sample/Logo.svg
rename to samples/ControlCatalog.Browser/Logo.svg
diff --git a/src/Web/Avalonia.Web.Sample/Program.cs b/samples/ControlCatalog.Browser/Program.cs
similarity index 76%
rename from src/Web/Avalonia.Web.Sample/Program.cs
rename to samples/ControlCatalog.Browser/Program.cs
index 52acabb0fa..53b7c60a6f 100644
--- a/src/Web/Avalonia.Web.Sample/Program.cs
+++ b/samples/ControlCatalog.Browser/Program.cs
@@ -1,7 +1,10 @@
+using System.Runtime.Versioning;
using Avalonia;
-using Avalonia.Web;
+using Avalonia.Browser;
using ControlCatalog;
-using ControlCatalog.Web;
+using ControlCatalog.Browser;
+
+[assembly:SupportedOSPlatform("browser")]
internal partial class Program
{
diff --git a/samples/ControlCatalog.Browser/Roots.xml b/samples/ControlCatalog.Browser/Roots.xml
new file mode 100644
index 0000000000..b07fd86fa2
--- /dev/null
+++ b/samples/ControlCatalog.Browser/Roots.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/Web/Avalonia.Web.Sample/app.css b/samples/ControlCatalog.Browser/app.css
similarity index 52%
rename from src/Web/Avalonia.Web.Sample/app.css
rename to samples/ControlCatalog.Browser/app.css
index 04ea5bee19..27680f6e1a 100644
--- a/src/Web/Avalonia.Web.Sample/app.css
+++ b/samples/ControlCatalog.Browser/app.css
@@ -4,12 +4,15 @@
}
#avalonia-splash {
- position: absolute;
+ position: relative;
height: 100%;
width: 100%;
color: whitesmoke;
background: #171C2C;
font-family: 'Nunito', sans-serif;
+ background-position: center;
+ background-size: cover;
+ background-repeat: no-repeat;
}
#avalonia-splash a{
@@ -24,15 +27,23 @@
}
.splash-close {
- animation: fadeOut 1s forwards;
+ animation: slide 0.5s linear 1s forwards;
}
-@keyframes fadeOut {
- from {
- opacity: 1;
+@keyframes slide {
+ 0% {
+ top: 0%;
}
- to {
+ 50% {
+ opacity: 80%;
+ }
+
+ 100% {
+ top: 100%;
+ overflow: hidden;
opacity: 0;
+ display: none;
+ visibility: collapse;
}
}
diff --git a/src/Web/Avalonia.Web.Sample/embed.js b/samples/ControlCatalog.Browser/embed.js
similarity index 100%
rename from src/Web/Avalonia.Web.Sample/embed.js
rename to samples/ControlCatalog.Browser/embed.js
diff --git a/src/Web/Avalonia.Web.Sample/favicon.ico b/samples/ControlCatalog.Browser/favicon.ico
similarity index 100%
rename from src/Web/Avalonia.Web.Sample/favicon.ico
rename to samples/ControlCatalog.Browser/favicon.ico
diff --git a/src/Web/Avalonia.Web.Sample/index.html b/samples/ControlCatalog.Browser/index.html
similarity index 95%
rename from src/Web/Avalonia.Web.Sample/index.html
rename to samples/ControlCatalog.Browser/index.html
index ee023790fb..226ae70695 100644
--- a/src/Web/Avalonia.Web.Sample/index.html
+++ b/samples/ControlCatalog.Browser/index.html
@@ -4,7 +4,7 @@
- Avalonia.Web.Sample
+ AvaloniaUI - ControlCatalog
diff --git a/src/Web/Avalonia.Web.Sample/main.js b/samples/ControlCatalog.Browser/main.js
similarity index 84%
rename from src/Web/Avalonia.Web.Sample/main.js
rename to samples/ControlCatalog.Browser/main.js
index 3683aea181..87f8a4f943 100644
--- a/src/Web/Avalonia.Web.Sample/main.js
+++ b/samples/ControlCatalog.Browser/main.js
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { dotnet } from './dotnet.js'
-import { createAvaloniaRuntime } from './avalonia.js';
+import { registerAvaloniaModule } from './avalonia.js';
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
@@ -12,7 +12,7 @@ const dotnetRuntime = await dotnet
.withApplicationArgumentsFromQuery()
.create();
-await createAvaloniaRuntime(dotnetRuntime);
+await registerAvaloniaModule(dotnetRuntime);
const config = dotnetRuntime.getConfig();
diff --git a/src/Web/Avalonia.Web.Sample/runtimeconfig.template.json b/samples/ControlCatalog.Browser/runtimeconfig.template.json
similarity index 100%
rename from src/Web/Avalonia.Web.Sample/runtimeconfig.template.json
rename to samples/ControlCatalog.Browser/runtimeconfig.template.json
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index 0667644643..e4c83dca49 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -5,6 +5,7 @@
net6.0
true
true
+ 6.0.8
diff --git a/samples/ControlCatalog.Web/App.razor.cs b/samples/ControlCatalog.Web/App.razor.cs
deleted file mode 100644
index bcd2a6fefc..0000000000
--- a/samples/ControlCatalog.Web/App.razor.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Avalonia;
-using Avalonia.Web.Blazor;
-
-namespace ControlCatalog.Web;
-
-public partial class App
-{
- protected override void OnParametersSet()
- {
- WebAppBuilder.Configure()
- .AfterSetup(_ =>
- {
- ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb();
- })
- .With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
- .SetupWithSingleViewLifetime();
-
- base.OnParametersSet();
- }
-}
diff --git a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
deleted file mode 100644
index b2c9ec72eb..0000000000
--- a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
- net6.0
- enable
-
- true
- 16777216
- false
- false
-
-
-
-
- false
- -O1
- false
-
-
-
- true
- true
- -O3
- -O3
- false
- false
- false
- false
- false
- false
- true
- false
- true
- true
- true
- link
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlCatalog.Web/EmbedSample.Browser.cs b/samples/ControlCatalog.Web/EmbedSample.Browser.cs
deleted file mode 100644
index 5fe14409de..0000000000
--- a/samples/ControlCatalog.Web/EmbedSample.Browser.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-
-using Avalonia;
-using Avalonia.Platform;
-using Avalonia.Web.Blazor;
-
-using ControlCatalog.Pages;
-
-using Microsoft.JSInterop;
-
-namespace ControlCatalog.Web;
-
-public class EmbedSampleWeb : INativeDemoControl
-{
- public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func createDefault)
- {
- var runtime = AvaloniaLocator.Current.GetRequiredService();
-
- if (isSecond)
- {
- var iframe = runtime.Invoke("document.createElement", "iframe");
- iframe.InvokeVoid("setAttribute", "src", "https://www.youtube.com/embed/kZCIporjJ70");
-
- return new JSObjectControlHandle(iframe);
- }
- else
- {
- // window.createAppButton source is defined in "app.js" file.
- var button = runtime.Invoke("window.createAppButton");
-
- return new JSObjectControlHandle(button);
- }
- }
-}
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index b228e72f72..8f32fa01dd 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ControlCatalog.ViewModels"
x:DataType="vm:ApplicationViewModel"
- x:CompileBindings="True"
Name="Avalonia ControlCatalog"
x:Class="ControlCatalog.App">
@@ -10,6 +9,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index 750c1082a6..6c99eb5289 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -3,85 +3,46 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
-using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
using Avalonia.Themes.Simple;
using Avalonia.Themes.Fluent;
+using ControlCatalog.Models;
using ControlCatalog.ViewModels;
namespace ControlCatalog
{
public class App : Application
{
+ private readonly Styles _themeStylesContainer = new();
+ private FluentTheme? _fluentTheme;
+ private SimpleTheme? _simpleTheme;
+ private IResourceDictionary? _fluentBaseLightColors, _fluentBaseDarkColors;
+ private IStyle? _colorPickerFluent, _colorPickerSimple;
+ private IStyle? _dataGridFluent, _dataGridSimple;
+
public App()
{
DataContext = new ApplicationViewModel();
}
- public static readonly StyleInclude ColorPickerFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
- {
- Source = new Uri("avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml")
- };
-
- public static readonly StyleInclude ColorPickerSimple = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
- {
- Source = new Uri("avares://Avalonia.Controls.ColorPicker/Themes/Simple/Simple.xaml")
- };
-
- public static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
- {
- Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml")
- };
-
- public static readonly StyleInclude DataGridSimple = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
- {
- Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml")
- };
-
- public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles"));
-
- public static SimpleTheme Simple = new SimpleTheme(new Uri("avares://ControlCatalog/Styles"));
-
- public static Styles SimpleLight = new Styles
- {
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
- },
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
- },
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml")
- },
- Simple
- };
-
- public static Styles SimpleDark = new Styles
- {
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
- },
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
- },
- new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
- {
- Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml")
- },
- Simple
- };
-
public override void Initialize()
{
- Styles.Insert(0, Fluent);
- Styles.Insert(1, ColorPickerFluent);
- Styles.Insert(2, DataGridFluent);
+ Styles.Add(_themeStylesContainer);
+
AvaloniaXamlLoader.Load(this);
+
+ _fluentTheme = new FluentTheme();
+ _simpleTheme = new SimpleTheme();
+ _simpleTheme.Resources.MergedDictionaries.Add((IResourceDictionary)Resources["FluentAccentColors"]!);
+ _simpleTheme.Resources.MergedDictionaries.Add((IResourceDictionary)Resources["FluentBaseColors"]!);
+ _colorPickerFluent = (IStyle)Resources["ColorPickerFluent"]!;
+ _colorPickerSimple = (IStyle)Resources["ColorPickerSimple"]!;
+ _dataGridFluent = (IStyle)Resources["DataGridFluent"]!;
+ _dataGridSimple = (IStyle)Resources["DataGridSimple"]!;
+ _fluentBaseLightColors = (IResourceDictionary)Resources["FluentBaseLightColors"]!;
+ _fluentBaseDarkColors = (IResourceDictionary)Resources["FluentBaseDarkColors"]!;
+
+ SetThemeVariant(CatalogTheme.FluentLight);
}
public override void OnFrameworkInitializationCompleted()
@@ -97,5 +58,78 @@ namespace ControlCatalog
base.OnFrameworkInitializationCompleted();
}
+
+ private CatalogTheme _prevTheme;
+ public static CatalogTheme CurrentTheme => ((App)Current!)._prevTheme;
+ public static void SetThemeVariant(CatalogTheme theme)
+ {
+ var app = (App)Current!;
+ var prevTheme = app._prevTheme;
+ app._prevTheme = theme;
+ var shouldReopenWindow = theme switch
+ {
+ CatalogTheme.FluentLight => prevTheme is CatalogTheme.SimpleDark or CatalogTheme.SimpleLight,
+ CatalogTheme.FluentDark => prevTheme is CatalogTheme.SimpleDark or CatalogTheme.SimpleLight,
+ CatalogTheme.SimpleLight => prevTheme is CatalogTheme.FluentDark or CatalogTheme.FluentLight,
+ CatalogTheme.SimpleDark => prevTheme is CatalogTheme.FluentDark or CatalogTheme.FluentLight,
+ _ => throw new ArgumentOutOfRangeException(nameof(theme), theme, null)
+ };
+
+ if (app._themeStylesContainer.Count == 0)
+ {
+ app._themeStylesContainer.Add(new Style());
+ app._themeStylesContainer.Add(new Style());
+ app._themeStylesContainer.Add(new Style());
+ }
+
+ if (theme == CatalogTheme.FluentLight)
+ {
+ app._fluentTheme!.Mode = FluentThemeMode.Light;
+ app._themeStylesContainer[0] = app._fluentTheme;
+ app._themeStylesContainer[1] = app._colorPickerFluent!;
+ app._themeStylesContainer[2] = app._dataGridFluent!;
+ }
+ else if (theme == CatalogTheme.FluentDark)
+ {
+ app._fluentTheme!.Mode = FluentThemeMode.Dark;
+ app._themeStylesContainer[0] = app._fluentTheme;
+ app._themeStylesContainer[1] = app._colorPickerFluent!;
+ app._themeStylesContainer[2] = app._dataGridFluent!;
+ }
+ else if (theme == CatalogTheme.SimpleLight)
+ {
+ app._simpleTheme!.Mode = SimpleThemeMode.Light;
+ app._simpleTheme.Resources.MergedDictionaries.Remove(app._fluentBaseDarkColors!);
+ app._simpleTheme.Resources.MergedDictionaries.Add(app._fluentBaseLightColors!);
+ app._themeStylesContainer[0] = app._simpleTheme;
+ app._themeStylesContainer[1] = app._colorPickerSimple!;
+ app._themeStylesContainer[2] = app._dataGridSimple!;
+ }
+ else if (theme == CatalogTheme.SimpleDark)
+ {
+ app._simpleTheme!.Mode = SimpleThemeMode.Dark;
+ app._simpleTheme.Resources.MergedDictionaries.Remove(app._fluentBaseLightColors!);
+ app._simpleTheme.Resources.MergedDictionaries.Add(app._fluentBaseDarkColors!);
+ app._themeStylesContainer[0] = app._simpleTheme;
+ app._themeStylesContainer[1] = app._colorPickerSimple!;
+ app._themeStylesContainer[2] = app._dataGridSimple!;
+ }
+
+ if (shouldReopenWindow)
+ {
+ if (app.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
+ {
+ var oldWindow = desktopLifetime.MainWindow;
+ var newWindow = new MainWindow();
+ desktopLifetime.MainWindow = newWindow;
+ newWindow.Show();
+ oldWindow?.Close();
+ }
+ else if (app.ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
+ {
+ singleViewLifetime.MainView = new MainView();
+ }
+ }
+ }
}
}
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 2654574a3e..6b550a30be 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -14,9 +14,6 @@
-
-
-
@@ -35,17 +32,5 @@
-
-
- MSBuild:Compile
-
-
-
-
-
- %(Filename)
-
-
-
diff --git a/samples/ControlCatalog/DecoratedWindow.xaml b/samples/ControlCatalog/DecoratedWindow.xaml
index c778b31c42..997ae54f41 100644
--- a/samples/ControlCatalog/DecoratedWindow.xaml
+++ b/samples/ControlCatalog/DecoratedWindow.xaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.DecoratedWindow"
Title="Avalonia Control Gallery"
- xmlns:local="clr-namespace:ControlCatalog" SystemDecorations="None" Name="Window">
+ SystemDecorations="None" Name="Window">
@@ -43,8 +43,13 @@
Hello world!
- Decorated
-
+
+
+ None
+ BorderOnly
+ Full
+
+
CanResize
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index ec198c6bba..b5a09b5fbd 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -1,9 +1,11 @@
+ xmlns:controls="using:ControlSamples"
+ xmlns:models="using:ControlCatalog.Models"
+ xmlns:pages="using:ControlCatalog.Pages"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:DataType="viewModels:MainWindowViewModel">
-
-
+
+
@@ -118,6 +120,9 @@
+
+
+
@@ -130,7 +135,7 @@
-
+
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index 7001eb41ea..15e666ae7b 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -6,7 +6,6 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Immutable;
-using Avalonia.Themes.Fluent;
using ControlCatalog.Models;
using ControlCatalog.Pages;
@@ -31,46 +30,12 @@ namespace ControlCatalog
}
var themes = this.Get("Themes");
+ themes.SelectedItem = App.CurrentTheme;
themes.SelectionChanged += (sender, e) =>
{
if (themes.SelectedItem is CatalogTheme theme)
{
- var themeStyle = Application.Current!.Styles[0];
- if (theme == CatalogTheme.FluentLight)
- {
- if (App.Fluent.Mode != FluentThemeMode.Light)
- {
- App.Fluent.Mode = FluentThemeMode.Light;
- }
- Application.Current.Styles[0] = App.Fluent;
- Application.Current.Styles[1] = App.ColorPickerFluent;
- Application.Current.Styles[2] = App.DataGridFluent;
- }
- else if (theme == CatalogTheme.FluentDark)
- {
-
- if (App.Fluent.Mode != FluentThemeMode.Dark)
- {
- App.Fluent.Mode = FluentThemeMode.Dark;
- }
- Application.Current.Styles[0] = App.Fluent;
- Application.Current.Styles[1] = App.ColorPickerFluent;
- Application.Current.Styles[2] = App.DataGridFluent;
- }
- else if (theme == CatalogTheme.SimpleLight)
- {
- App.Simple.Mode = Avalonia.Themes.Simple.SimpleThemeMode.Light;
- Application.Current.Styles[0] = App.SimpleLight;
- Application.Current.Styles[1] = App.ColorPickerSimple;
- Application.Current.Styles[2] = App.DataGridSimple;
- }
- else if (theme == CatalogTheme.SimpleDark)
- {
- App.Simple.Mode = Avalonia.Themes.Simple.SimpleThemeMode.Dark;
- Application.Current.Styles[0] = App.SimpleDark;
- Application.Current.Styles[1] = App.ColorPickerSimple;
- Application.Current.Styles[2] = App.DataGridSimple;
- }
+ App.SetThemeVariant(theme);
}
};
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index d5513904c0..cebb3e0916 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -1,19 +1,20 @@
+ x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}"
+ x:DataType="vm:MainWindowViewModel">
diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs
index c61296ac8f..c589f41442 100644
--- a/samples/ControlCatalog/MainWindow.xaml.cs
+++ b/samples/ControlCatalog/MainWindow.xaml.cs
@@ -11,23 +11,13 @@ namespace ControlCatalog
{
public class MainWindow : Window
{
- private WindowNotificationManager _notificationArea;
private NativeMenu? _recentMenu;
public MainWindow()
{
this.InitializeComponent();
- //Renderer.DrawFps = true;
- //Renderer.DrawDirtyRects = Renderer.DrawFps = true;
-
- _notificationArea = new WindowNotificationManager(this)
- {
- Position = NotificationPosition.TopRight,
- MaxItems = 3
- };
-
- DataContext = new MainWindowViewModel(_notificationArea);
+ DataContext = new MainWindowViewModel();
_recentMenu = ((NativeMenu.GetMenu(this)?.Items[0] as NativeMenuItem)?.Menu?.Items[2] as NativeMenuItem)?.Menu;
}
diff --git a/samples/ControlCatalog/Models/StateData.cs b/samples/ControlCatalog/Models/StateData.cs
new file mode 100644
index 0000000000..bd6d186252
--- /dev/null
+++ b/samples/ControlCatalog/Models/StateData.cs
@@ -0,0 +1,20 @@
+namespace ControlCatalog.Models;
+
+public class StateData
+{
+ public string Name { get; private set; }
+ public string Abbreviation { get; private set; }
+ public string Capital { get; private set; }
+
+ public StateData(string name, string abbreviatoin, string capital)
+ {
+ Name = name;
+ Abbreviation = abbreviatoin;
+ Capital = capital;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+}
\ No newline at end of file
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
index faa12bc8da..a492808f1d 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
@@ -2,8 +2,8 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:sys="clr-namespace:System;assembly=netstandard"
+ xmlns:sys="using:System"
+ xmlns:models="using:ControlCatalog.Models"
d:DesignHeight="600"
d:DesignWidth="400">
-
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
index bc18327f12..8d9cd74ea7 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
@@ -8,30 +8,12 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Data.Converters;
using Avalonia.Data;
+using ControlCatalog.Models;
namespace ControlCatalog.Pages
{
public class AutoCompleteBoxPage : UserControl
{
- public class StateData
- {
- public string Name { get; private set; }
- public string Abbreviation { get; private set; }
- public string Capital { get; private set; }
-
- public StateData(string name, string abbreviatoin, string capital)
- {
- Name = name;
- Abbreviation = abbreviatoin;
- Capital = capital;
- }
-
- public override string ToString()
- {
- return Name;
- }
- }
-
private StateData[] BuildAllStates()
{
return new StateData[]
diff --git a/samples/ControlCatalog/Pages/BorderPage.xaml b/samples/ControlCatalog/Pages/BorderPage.xaml
index bfc4f86698..7ec7e81e80 100644
--- a/samples/ControlCatalog/Pages/BorderPage.xaml
+++ b/samples/ControlCatalog/Pages/BorderPage.xaml
@@ -1,7 +1,6 @@
diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
index 323d6d36e9..900e304559 100644
--- a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
+++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
@@ -1,7 +1,7 @@
+ xmlns:sys="using:System">
The ButtonSpinner control allows you to add button spinners to any element and then respond to the Spin event to manipulate that element.
diff --git a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
index aef96802f4..7a22c0ddab 100644
--- a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
@@ -1,6 +1,6 @@
diff --git a/samples/ControlCatalog/Pages/ColorPickerPage.xaml b/samples/ControlCatalog/Pages/ColorPickerPage.xaml
index ad54eb95fc..649256ba83 100644
--- a/samples/ControlCatalog/Pages/ColorPickerPage.xaml
+++ b/samples/ControlCatalog/Pages/ColorPickerPage.xaml
@@ -2,39 +2,39 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:controls="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.ColorPicker"
- xmlns:primitives="clr-namespace:Avalonia.Controls.Primitives;assembly=Avalonia.Controls"
- xmlns:pc="clr-namespace:Avalonia.Controls.Primitives.Converters;assembly=Avalonia.Controls.ColorPicker"
+ xmlns:controls="using:Avalonia.Controls"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="ControlCatalog.Pages.ColorPickerPage">
-
-
-
+
+ RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
+
-
+
+
-
-
diff --git a/samples/ControlCatalog/Pages/ColorPickerPage.xaml.cs b/samples/ControlCatalog/Pages/ColorPickerPage.xaml.cs
index 6e017e381f..52d63ded32 100644
--- a/samples/ControlCatalog/Pages/ColorPickerPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ColorPickerPage.xaml.cs
@@ -1,6 +1,8 @@
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Layout;
using Avalonia.Markup.Xaml;
+using Avalonia.Media;
namespace ControlCatalog.Pages
{
@@ -9,6 +11,21 @@ namespace ControlCatalog.Pages
public ColorPickerPage()
{
InitializeComponent();
+
+ var layoutRoot = this.GetControl("LayoutRoot");
+
+ // ColorPicker added from code-behind
+ var colorPicker = new ColorPicker()
+ {
+ Color = Colors.Blue,
+ Margin = new Thickness(0, 50, 0, 0),
+ HorizontalAlignment = HorizontalAlignment.Center,
+ Palette = new MaterialHalfColorPalette(),
+ };
+ Grid.SetColumn(colorPicker, 2);
+ Grid.SetRow(colorPicker, 1);
+
+ layoutRoot.Children.Add(colorPicker);
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index 9f2fbb88f3..748a46c447 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -3,7 +3,9 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:col="using:System.Collections"
- xmlns:sys="using:System">
+ xmlns:sys="using:System"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:DataType="viewModels:ComboBoxPageViewModel">
A drop-down list.
@@ -39,7 +41,7 @@
-
+
@@ -71,7 +73,7 @@
SelectedIndex="0"
WrapSelection="{Binding WrapSelection}">
-
+
diff --git a/samples/ControlCatalog/Pages/CompositionPage.axaml b/samples/ControlCatalog/Pages/CompositionPage.axaml
index 22c5c88941..403f45b8eb 100644
--- a/samples/ControlCatalog/Pages/CompositionPage.axaml
+++ b/samples/ControlCatalog/Pages/CompositionPage.axaml
@@ -1,6 +1,6 @@
Implicit animations
@@ -42,4 +42,4 @@
-
\ No newline at end of file
+
diff --git a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml
index 871efa5b7a..6ef6a202b6 100644
--- a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml
+++ b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml
@@ -3,9 +3,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
- mc:Ignorable="d">
+ mc:Ignorable="d"
+ x:DataType="viewModels:ContextPageViewModel">
diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml
index 27272a9ff7..f1fcd8035a 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml
@@ -4,13 +4,13 @@
x:Class="ControlCatalog.Pages.DataGridPage">
-
+
-
+
@@ -49,15 +49,15 @@
AlternatingRowBackground="#1fff">
-
-
+
-
-
+
+
+ IsVisible="{Binding #ShowGDP.IsChecked}"
+ x:DataType="local:Country" />
@@ -65,11 +65,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -77,9 +77,9 @@
-
-
-
+
+
+
diff --git a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
index 29cd939520..47753f56b6 100644
--- a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:sys="clr-namespace:System;assembly=netstandard"
+ xmlns:sys="using:System"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ControlCatalog.Pages.DateTimePickerPage">
@@ -13,17 +13,17 @@
Margin="16"
HorizontalAlignment="Stretch"
Spacing="16">
- A simple DatePicker with a header
+ A simple DatePicker
-
+
- <DatePicker Header="Pick a date" />
+ <DatePicker/>
@@ -33,7 +33,7 @@
-
+
@@ -79,24 +79,24 @@
-
+
- A TimePicker with a header and minute increments specified.
+ A TimePicker with minute increments specified.
-
+
- <TimePicker Header="Arrival time" MinuteIncrement="15" />
+ <TimePicker MinuteIncrement="15" />
@@ -107,13 +107,13 @@
-
+
- <TimePicker ClockIdentifier="12HourClock" Header="12 hour clock" />
+ <TimePicker ClockIdentifier="12HourClock" />
@@ -124,13 +124,13 @@
-
+
- <TimePicker ClockIdentifier="24HourClock" Header="24 hour clock" />
+ <TimePicker ClockIdentifier="24HourClock" />
diff --git a/samples/ControlCatalog/Pages/ExpanderPage.xaml b/samples/ControlCatalog/Pages/ExpanderPage.xaml
index f9ae1c7a3c..f0a80fd7ab 100644
--- a/samples/ControlCatalog/Pages/ExpanderPage.xaml
+++ b/samples/ControlCatalog/Pages/ExpanderPage.xaml
@@ -1,6 +1,8 @@
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:Class="ControlCatalog.Pages.ExpanderPage"
+ x:DataType="viewModels:ExpanderPageViewModel">
Expands to show nested content
@@ -32,6 +34,23 @@
Expanded content
+
+
+
+
+
+ Expanded content
+
+
+
+
+ Expanded content
+
+
Rounded
diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
index 1d42b92096..5ca4ca9bdd 100644
--- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
+++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
@@ -1,6 +1,8 @@
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:Class="ControlCatalog.Pages.ItemsRepeaterPage"
+ x:DataType="viewModels:ItemsRepeaterPageViewModel">
diff --git a/samples/ControlCatalog/Pages/NotificationsPage.xaml b/samples/ControlCatalog/Pages/NotificationsPage.xaml
index d48b338fe8..46c1fe52de 100644
--- a/samples/ControlCatalog/Pages/NotificationsPage.xaml
+++ b/samples/ControlCatalog/Pages/NotificationsPage.xaml
@@ -1,6 +1,8 @@
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:Class="ControlCatalog.Pages.NotificationsPage"
+ x:DataType="viewModels:NotificationViewModel">
diff --git a/samples/ControlCatalog/Pages/NotificationsPage.xaml.cs b/samples/ControlCatalog/Pages/NotificationsPage.xaml.cs
index eadf92b602..bfd49a2c00 100644
--- a/samples/ControlCatalog/Pages/NotificationsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/NotificationsPage.xaml.cs
@@ -1,18 +1,33 @@
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
public class NotificationsPage : UserControl
{
+ private NotificationViewModel _viewModel;
+
public NotificationsPage()
{
this.InitializeComponent();
+
+ _viewModel = new NotificationViewModel();
+
+ DataContext = _viewModel;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ _viewModel.NotificationManager = new Avalonia.Controls.Notifications.WindowNotificationManager(VisualRoot as TopLevel);
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
index 045ba4a059..e76787f184 100644
--- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
+++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
@@ -1,8 +1,10 @@
+ xmlns:sys="using:System"
+ xmlns:converter="using:ControlCatalog.Converter"
+ xmlns:pages="using:ControlCatalog.Pages"
+ x:Class="ControlCatalog.Pages.NumericUpDownPage"
+ x:DataType="pages:NumbersPageViewModel">
Numeric up-down control provides a TextBox with button spinners that allow incrementing and decrementing numeric values by using the spinner buttons, keyboard up/down arrows, or mouse wheel.
@@ -43,7 +45,7 @@
VerticalAlignment="Center" Margin="2"/>
CultureInfo:
-
Watermark:
@@ -77,6 +79,7 @@
diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml.cs b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml.cs
index edd4921632..8785eac354 100644
--- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia.Controls;
+using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;
using MiniMvvm;
@@ -22,6 +23,8 @@ namespace ControlCatalog.Pages
AvaloniaXamlLoader.Load(this);
}
+ public static IValueConverter CultureConverter =
+ new FuncValueConverter(c => (c ?? CultureInfo.CurrentCulture).NumberFormat);
}
public class NumbersPageViewModel : ViewModelBase
diff --git a/samples/ControlCatalog/Pages/OpenGlPage.xaml b/samples/ControlCatalog/Pages/OpenGlPage.xaml
index 0eb09004ba..2a97956e30 100644
--- a/samples/ControlCatalog/Pages/OpenGlPage.xaml
+++ b/samples/ControlCatalog/Pages/OpenGlPage.xaml
@@ -1,7 +1,7 @@
+ xmlns:pages="using:ControlCatalog.Pages">
diff --git a/samples/ControlCatalog/Pages/PlatformInfoPage.xaml b/samples/ControlCatalog/Pages/PlatformInfoPage.xaml
new file mode 100644
index 0000000000..f02741d2da
--- /dev/null
+++ b/samples/ControlCatalog/Pages/PlatformInfoPage.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/PlatformInfoPage.xaml.cs b/samples/ControlCatalog/Pages/PlatformInfoPage.xaml.cs
new file mode 100644
index 0000000000..1f37451782
--- /dev/null
+++ b/samples/ControlCatalog/Pages/PlatformInfoPage.xaml.cs
@@ -0,0 +1,20 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using ControlCatalog.ViewModels;
+
+namespace ControlCatalog.Pages
+{
+ public class PlatformInfoPage : UserControl
+ {
+ public PlatformInfoPage()
+ {
+ this.InitializeComponent();
+ DataContext = new PlatformInformationViewModel();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/samples/ControlCatalog/Pages/ProgressBarPage.xaml b/samples/ControlCatalog/Pages/ProgressBarPage.xaml
index 8e73f1d0f5..dcddcd5965 100644
--- a/samples/ControlCatalog/Pages/ProgressBarPage.xaml
+++ b/samples/ControlCatalog/Pages/ProgressBarPage.xaml
@@ -31,7 +31,7 @@
+ Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}"/>
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index 823f59e030..ff62b834c4 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -62,10 +62,10 @@ namespace ControlCatalog.Pages
CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
- formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%");
+ formattedText = CreateFormattedText($"Scaling: {screen.Scaling * 100}%");
context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
- formattedText = CreateFormattedText($"Primary: {screen.Primary}");
+ formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}");
context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
formattedText =
diff --git a/samples/ControlCatalog/Pages/ScrollViewerPage.xaml b/samples/ControlCatalog/Pages/ScrollViewerPage.xaml
index 1b3771ccb5..1903e50ed7 100644
--- a/samples/ControlCatalog/Pages/ScrollViewerPage.xaml
+++ b/samples/ControlCatalog/Pages/ScrollViewerPage.xaml
@@ -1,6 +1,8 @@
+ xmlns:pages="using:ControlCatalog.Pages"
+ x:Class="ControlCatalog.Pages.ScrollViewerPage"
+ x:DataType="pages:ScrollViewerPageViewModel">
Allows for horizontal and vertical content scrolling.
diff --git a/samples/ControlCatalog/Pages/SliderPage.xaml b/samples/ControlCatalog/Pages/SliderPage.xaml
index b2375922c2..9aa4322ad5 100644
--- a/samples/ControlCatalog/Pages/SliderPage.xaml
+++ b/samples/ControlCatalog/Pages/SliderPage.xaml
@@ -1,6 +1,6 @@
A control that lets the user select from a range of values by moving a Thumb control along a Track.
diff --git a/samples/ControlCatalog/Pages/SplitViewPage.xaml b/samples/ControlCatalog/Pages/SplitViewPage.xaml
index 6902b27715..61bfb490b8 100644
--- a/samples/ControlCatalog/Pages/SplitViewPage.xaml
+++ b/samples/ControlCatalog/Pages/SplitViewPage.xaml
@@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="ControlCatalog.Pages.SplitViewPage">
+ x:Class="ControlCatalog.Pages.SplitViewPage"
+ x:DataType="viewModels:SplitViewPageViewModel">
@@ -51,7 +53,7 @@
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml
index 90afb5ceca..8e353cf651 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml
@@ -1,7 +1,9 @@
+ xmlns="https://github.com/avaloniaui"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:DataType="viewModels:TabControlPageViewModel">
-
+
@@ -62,7 +64,7 @@
-
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
index bd0214c72e..74e9928b24 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
@@ -5,8 +5,7 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
-
-using MiniMvvm;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -18,23 +17,23 @@ namespace ControlCatalog.Pages
{
InitializeComponent();
- DataContext = new PageViewModel
+ DataContext = new TabControlPageViewModel
{
Tabs = new[]
{
- new TabItemViewModel
+ new TabControlPageViewModelItem
{
Header = "Arch",
Text = "This is the first templated tab page.",
Image = LoadBitmap("avares://ControlCatalog/Assets/delicate-arch-896885_640.jpg"),
},
- new TabItemViewModel
+ new TabControlPageViewModelItem
{
Header = "Leaf",
Text = "This is the second templated tab page.",
Image = LoadBitmap("avares://ControlCatalog/Assets/maple-leaf-888807_640.jpg"),
},
- new TabItemViewModel
+ new TabControlPageViewModelItem
{
Header = "Disabled",
Text = "You should not see this.",
@@ -55,26 +54,5 @@ namespace ControlCatalog.Pages
var assets = AvaloniaLocator.Current!.GetService()!;
return new Bitmap(assets.Open(new Uri(uri)));
}
-
- private class PageViewModel : ViewModelBase
- {
- private Dock _tabPlacement;
-
- public TabItemViewModel[]? Tabs { get; set; }
-
- public Dock TabPlacement
- {
- get { return _tabPlacement; }
- set { this.RaiseAndSetIfChanged(ref _tabPlacement, value); }
- }
- }
-
- private class TabItemViewModel
- {
- public string? Header { get; set; }
- public string? Text { get; set; }
- public IBitmap? Image { get; set; }
- public bool IsEnabled { get; set; } = true;
- }
}
}
diff --git a/samples/ControlCatalog/Pages/TabStripPage.xaml b/samples/ControlCatalog/Pages/TabStripPage.xaml
index 163665ef92..533590b48d 100644
--- a/samples/ControlCatalog/Pages/TabStripPage.xaml
+++ b/samples/ControlCatalog/Pages/TabStripPage.xaml
@@ -1,6 +1,8 @@
+ xmlns="https://github.com/avaloniaui"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:DataType="viewModels:TabControlPageViewModel">
A control which displays a selectable strip of tabs
@@ -16,14 +18,14 @@
Dynamically generated
-
+
-
-
+
diff --git a/samples/ControlCatalog/Pages/TabStripPage.xaml.cs b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs
index 6d7135a90f..20fae13bbf 100644
--- a/samples/ControlCatalog/Pages/TabStripPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs
@@ -1,9 +1,6 @@
-using System;
-using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
-using Avalonia.Media.Imaging;
-using Avalonia.Platform;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -13,21 +10,24 @@ namespace ControlCatalog.Pages
{
InitializeComponent();
- DataContext = new[]
+ DataContext = new TabControlPageViewModel
{
- new TabStripItemViewModel
+ Tabs = new []
{
- Header = "Item 1",
- },
- new TabStripItemViewModel
- {
- Header = "Item 2",
- },
- new TabStripItemViewModel
- {
- Header = "Disabled",
- IsEnabled = false,
- },
+ new TabControlPageViewModelItem()
+ {
+ Header = "Item 1",
+ },
+ new TabControlPageViewModelItem
+ {
+ Header = "Item 2",
+ },
+ new TabControlPageViewModelItem
+ {
+ Header = "Disabled",
+ IsEnabled = false,
+ },
+ }
};
}
@@ -35,11 +35,5 @@ namespace ControlCatalog.Pages
{
AvaloniaXamlLoader.Load(this);
}
-
- private class TabStripItemViewModel
- {
- public string? Header { get; set; }
- public bool IsEnabled { get; set; } = true;
- }
}
}
diff --git a/samples/ControlCatalog/Pages/TextBlockPage.xaml b/samples/ControlCatalog/Pages/TextBlockPage.xaml
index 32914428ed..6bb428e2c7 100644
--- a/samples/ControlCatalog/Pages/TextBlockPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBlockPage.xaml
@@ -118,7 +118,7 @@
-
+
This is a
TextBlock
with several
@@ -126,7 +126,7 @@
using a variety of styles
.
-
+
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index e3d0c5e4e2..6a4d9b7d0e 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -1,7 +1,7 @@
+ xmlns:sys="using:System">
diff --git a/samples/ControlCatalog/Pages/TransitioningContentControlPage.axaml b/samples/ControlCatalog/Pages/TransitioningContentControlPage.axaml
index a410577d27..42042652e3 100644
--- a/samples/ControlCatalog/Pages/TransitioningContentControlPage.axaml
+++ b/samples/ControlCatalog/Pages/TransitioningContentControlPage.axaml
@@ -3,11 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:ControlCatalog.ViewModels"
- xmlns:converter="clr-namespace:ControlCatalog.Converter"
+ xmlns:converter="using:ControlCatalog.Converter"
xmlns:system="using:System"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="vm:TransitioningContentControlPageViewModel"
- x:CompileBindings="True"
x:Class="ControlCatalog.Pages.TransitioningContentControlPage">
diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml b/samples/ControlCatalog/Pages/TreeViewPage.xaml
index 31f4d73581..1665a59c0a 100644
--- a/samples/ControlCatalog/Pages/TreeViewPage.xaml
+++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml
@@ -1,6 +1,8 @@
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:Class="ControlCatalog.Pages.TreeViewPage"
+ x:DataType="viewModels:TreeViewPageViewModel">
Displays a hierachical tree of data.
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml
index e7e3007d35..a31a52d238 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml
@@ -1,6 +1,6 @@
diff --git a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
index caab42e98c..f1403905c4 100644
--- a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
+++ b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
@@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="ControlCatalog.Pages.WindowCustomizationsPage">
+ x:Class="ControlCatalog.Pages.WindowCustomizationsPage"
+ x:DataType="viewModels:MainWindowViewModel">
diff --git a/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs b/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
index d73ab810eb..8a3f0ba947 100644
--- a/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
@@ -27,18 +27,18 @@ namespace ControlCatalog.ViewModels
public IEnumerable StandardCursors { get; }
public Cursor CustomCursor { get; }
-
- public class StandardCursorModel
+ }
+
+ public class StandardCursorModel
+ {
+ public StandardCursorModel(StandardCursorType type)
{
- public StandardCursorModel(StandardCursorType type)
- {
- Type = type;
- Cursor = new Cursor(type);
- }
+ Type = type;
+ Cursor = new Cursor(type);
+ }
- public StandardCursorType Type { get; }
+ public StandardCursorType Type { get; }
- public Cursor Cursor { get; }
- }
+ public Cursor Cursor { get; }
}
}
diff --git a/samples/ControlCatalog/ViewModels/ItemsRepeaterPageViewModel.cs b/samples/ControlCatalog/ViewModels/ItemsRepeaterPageViewModel.cs
index 3973c73662..8f8a959867 100644
--- a/samples/ControlCatalog/ViewModels/ItemsRepeaterPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ItemsRepeaterPageViewModel.cs
@@ -10,25 +10,25 @@ namespace ControlCatalog.ViewModels
{
private int _newItemIndex = 1;
private int _newGenerationIndex = 0;
- private ObservableCollection- _items;
+ private ObservableCollection _items;
public ItemsRepeaterPageViewModel()
{
_items = CreateItems();
}
- public ObservableCollection
- Items
+ public ObservableCollection Items
{
get => _items;
set => this.RaiseAndSetIfChanged(ref _items, value);
}
- public Item? SelectedItem { get; set; }
+ public ItemsRepeaterPageViewModelItem? SelectedItem { get; set; }
public void AddItem()
{
var index = SelectedItem != null ? Items.IndexOf(SelectedItem) : -1;
- Items.Insert(index + 1, new Item(index + 1, $"New Item {_newItemIndex++}"));
+ Items.Insert(index + 1, new ItemsRepeaterPageViewModelItem(index + 1, $"New Item {_newItemIndex++}"));
}
public void RemoveItem()
@@ -59,33 +59,33 @@ namespace ControlCatalog.ViewModels
Items = CreateItems();
}
- private ObservableCollection
- CreateItems()
+ private ObservableCollection CreateItems()
{
var suffix = _newGenerationIndex == 0 ? string.Empty : $"[{_newGenerationIndex.ToString()}]";
_newGenerationIndex++;
- return new ObservableCollection
- (
- Enumerable.Range(1, 100000).Select(i => new Item(i, $"Item {i.ToString()} {suffix}")));
+ return new ObservableCollection(
+ Enumerable.Range(1, 100000).Select(i => new ItemsRepeaterPageViewModelItem(i, $"Item {i.ToString()} {suffix}")));
}
+ }
+
+ public class ItemsRepeaterPageViewModelItem : ViewModelBase
+ {
+ private double _height = double.NaN;
- public class Item : ViewModelBase
+ public ItemsRepeaterPageViewModelItem(int index, string text)
{
- private double _height = double.NaN;
-
- public Item(int index, string text)
- {
- Index = index;
- Text = text;
- }
- public int Index { get; }
- public string Text { get; }
+ Index = index;
+ Text = text;
+ }
+ public int Index { get; }
+ public string Text { get; }
- public double Height
- {
- get => _height;
- set => this.RaiseAndSetIfChanged(ref _height, value);
- }
+ public double Height
+ {
+ get => _height;
+ set => this.RaiseAndSetIfChanged(ref _height, value);
}
}
}
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
index c2c2462246..b79eff780c 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
@@ -24,25 +24,8 @@ namespace ControlCatalog.ViewModels
private bool _preferSystemChromeEnabled;
private double _titleBarHeight;
- public MainWindowViewModel(IManagedNotificationManager notificationManager)
+ public MainWindowViewModel()
{
- _notificationManager = notificationManager;
-
- ShowCustomManagedNotificationCommand = MiniCommand.Create(() =>
- {
- NotificationManager.Show(new NotificationViewModel(NotificationManager) { Title = "Hey There!", Message = "Did you know that Avalonia now supports Custom In-Window Notifications?" });
- });
-
- ShowManagedNotificationCommand = MiniCommand.Create(() =>
- {
- NotificationManager.Show(new Avalonia.Controls.Notifications.Notification("Welcome", "Avalonia now supports Notifications.", NotificationType.Information));
- });
-
- ShowNativeNotificationCommand = MiniCommand.Create(() =>
- {
- NotificationManager.Show(new Avalonia.Controls.Notifications.Notification("Error", "Native Notifications are not quite ready. Coming soon.", NotificationType.Error));
- });
-
AboutCommand = MiniCommand.CreateFromTask(async () =>
{
var dialog = new AboutAvaloniaDialog();
@@ -52,7 +35,6 @@ namespace ControlCatalog.ViewModels
await dialog.ShowDialog(mainWindow);
}
});
-
ExitCommand = MiniCommand.Create(() =>
{
(App.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown();
@@ -143,24 +125,12 @@ namespace ControlCatalog.ViewModels
set { this.RaiseAndSetIfChanged(ref _windowStates, value); }
}
- public IManagedNotificationManager NotificationManager
- {
- get { return _notificationManager; }
- set { this.RaiseAndSetIfChanged(ref _notificationManager, value); }
- }
-
public bool IsMenuItemChecked
{
get { return _isMenuItemChecked; }
set { this.RaiseAndSetIfChanged(ref _isMenuItemChecked, value); }
}
- public MiniCommand ShowCustomManagedNotificationCommand { get; }
-
- public MiniCommand ShowManagedNotificationCommand { get; }
-
- public MiniCommand ShowNativeNotificationCommand { get; }
-
public MiniCommand AboutCommand { get; }
public MiniCommand ExitCommand { get; }
diff --git a/samples/ControlCatalog/ViewModels/NotificationViewModel.cs b/samples/ControlCatalog/ViewModels/NotificationViewModel.cs
index b714c319a6..a31f164a2a 100644
--- a/samples/ControlCatalog/ViewModels/NotificationViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/NotificationViewModel.cs
@@ -6,16 +6,33 @@ namespace ControlCatalog.ViewModels
{
public class NotificationViewModel
{
- public NotificationViewModel(INotificationManager manager)
+ public WindowNotificationManager? NotificationManager { get; set; }
+
+ public NotificationViewModel()
{
+ ShowCustomManagedNotificationCommand = MiniCommand.Create(() =>
+ {
+ NotificationManager?.Show(new NotificationViewModel() { Title = "Hey There!", Message = "Did you know that Avalonia now supports Custom In-Window Notifications?" , NotificationManager = NotificationManager});
+ });
+
+ ShowManagedNotificationCommand = MiniCommand.Create(() =>
+ {
+ NotificationManager?.Show(new Avalonia.Controls.Notifications.Notification("Welcome", "Avalonia now supports Notifications.", NotificationType.Information));
+ });
+
+ ShowNativeNotificationCommand = MiniCommand.Create(() =>
+ {
+ NotificationManager?.Show(new Avalonia.Controls.Notifications.Notification("Error", "Native Notifications are not quite ready. Coming soon.", NotificationType.Error));
+ });
+
YesCommand = MiniCommand.Create(() =>
{
- manager.Show(new Avalonia.Controls.Notifications.Notification("Avalonia Notifications", "Start adding notifications to your app today."));
+ NotificationManager?.Show(new Avalonia.Controls.Notifications.Notification("Avalonia Notifications", "Start adding notifications to your app today."));
});
NoCommand = MiniCommand.Create(() =>
{
- manager.Show(new Avalonia.Controls.Notifications.Notification("Avalonia Notifications", "Start adding notifications to your app today. To find out more visit..."));
+ NotificationManager?.Show(new Avalonia.Controls.Notifications.Notification("Avalonia Notifications", "Start adding notifications to your app today. To find out more visit..."));
});
}
@@ -26,5 +43,11 @@ namespace ControlCatalog.ViewModels
public MiniCommand NoCommand { get; }
+ public MiniCommand ShowCustomManagedNotificationCommand { get; }
+
+ public MiniCommand ShowManagedNotificationCommand { get; }
+
+ public MiniCommand ShowNativeNotificationCommand { get; }
+
}
}
diff --git a/samples/ControlCatalog/ViewModels/PlatformInformationViewModel.cs b/samples/ControlCatalog/ViewModels/PlatformInformationViewModel.cs
new file mode 100644
index 0000000000..e4f6c3ac73
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/PlatformInformationViewModel.cs
@@ -0,0 +1,54 @@
+using Avalonia;
+using Avalonia.Platform;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels;
+#nullable enable
+
+public class PlatformInformationViewModel : ViewModelBase
+{
+ public PlatformInformationViewModel()
+ {
+ var runtimeInfo = AvaloniaLocator.Current.GetService()?.GetRuntimeInfo();
+
+ if (runtimeInfo is { } info)
+ {
+ if (info.IsBrowser)
+ {
+ if (info.IsDesktop)
+ {
+ PlatformInfo = "Platform: Desktop (browser)";
+ }
+ else if (info.IsMobile)
+ {
+ PlatformInfo = "Platform: Mobile (browser)";
+ }
+ else
+ {
+ PlatformInfo = "Platform: Unknown (browser) - please report";
+ }
+ }
+ else
+ {
+ if (info.IsDesktop)
+ {
+ PlatformInfo = "Platform: Desktop (native)";
+ }
+ else if (info.IsMobile)
+ {
+ PlatformInfo = "Platform: Mobile (native)";
+ }
+ else
+ {
+ PlatformInfo = "Platform: Unknown (native) - please report";
+ }
+ }
+ }
+ else
+ {
+
+ }
+ }
+
+ public string PlatformInfo { get; }
+}
diff --git a/samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs b/samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs
new file mode 100644
index 0000000000..b0e560b001
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs
@@ -0,0 +1,26 @@
+using Avalonia.Controls;
+using Avalonia.Media.Imaging;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels;
+
+public class TabControlPageViewModel : ViewModelBase
+{
+ private Dock _tabPlacement;
+
+ public TabControlPageViewModelItem[]? Tabs { get; set; }
+
+ public Dock TabPlacement
+ {
+ get { return _tabPlacement; }
+ set { this.RaiseAndSetIfChanged(ref _tabPlacement, value); }
+ }
+}
+
+public class TabControlPageViewModelItem
+{
+ public string? Header { get; set; }
+ public string? Text { get; set; }
+ public IBitmap? Image { get; set; }
+ public bool IsEnabled { get; set; } = true;
+}
diff --git a/samples/ControlCatalog/Views/CustomNotificationView.xaml b/samples/ControlCatalog/Views/CustomNotificationView.xaml
index 5b99ed8e4d..f06ea029a8 100644
--- a/samples/ControlCatalog/Views/CustomNotificationView.xaml
+++ b/samples/ControlCatalog/Views/CustomNotificationView.xaml
@@ -1,6 +1,8 @@
+ xmlns:viewModels="using:ControlCatalog.ViewModels"
+ x:Class="ControlCatalog.Views.CustomNotificationView"
+ x:DataType="viewModels:NotificationViewModel">
diff --git a/samples/IntegrationTestApp/IntegrationTestApp.csproj b/samples/IntegrationTestApp/IntegrationTestApp.csproj
index 4284399357..0a761d70ba 100644
--- a/samples/IntegrationTestApp/IntegrationTestApp.csproj
+++ b/samples/IntegrationTestApp/IntegrationTestApp.csproj
@@ -1,7 +1,7 @@
WinExe
- net6.0
+ net7.0
enable
diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml
index 3377979199..038ced4e5c 100644
--- a/samples/IntegrationTestApp/MainWindow.axaml
+++ b/samples/IntegrationTestApp/MainWindow.axaml
@@ -2,10 +2,12 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:integrationTestApp="using:IntegrationTestApp"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="IntegrationTestApp.MainWindow"
Name="MainWindow"
- Title="IntegrationTestApp">
+ Title="IntegrationTestApp"
+ x:DataType="integrationTestApp:MainWindow">
@@ -69,6 +71,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -109,6 +128,12 @@
CenterScreen
CenterOwner
+
+ Normal
+ Minimized
+ Maximized
+ FullScreen
+
diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs
index f72f83fcb8..c1acc7ca88 100644
--- a/samples/IntegrationTestApp/MainWindow.axaml.cs
+++ b/samples/IntegrationTestApp/MainWindow.axaml.cs
@@ -4,6 +4,7 @@ using Avalonia;
using Avalonia.Automation;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.VisualTree;
@@ -17,6 +18,7 @@ namespace IntegrationTestApp
{
InitializeComponent();
InitializeViewMenu();
+ InitializeGesturesTab();
this.AttachDevTools();
AddHandler(Button.ClickEvent, OnButtonClick);
ListBoxItems = Enumerable.Range(0, 100).Select(x => "Item " + x).ToList();
@@ -57,6 +59,7 @@ namespace IntegrationTestApp
var sizeTextBox = this.GetControl("ShowWindowSize");
var modeComboBox = this.GetControl("ShowWindowMode");
var locationComboBox = this.GetControl("ShowWindowLocation");
+ var stateComboBox = this.GetControl("ShowWindowState");
var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
var owner = (Window)this.GetVisualRoot()!;
@@ -83,6 +86,7 @@ namespace IntegrationTestApp
}
sizeTextBox.Text = string.Empty;
+ window.WindowState = (WindowState)stateComboBox.SelectedIndex;
switch (modeComboBox.SelectedIndex)
{
@@ -120,6 +124,38 @@ namespace IntegrationTestApp
}
}
+ private void InitializeGesturesTab()
+ {
+ var gestureBorder = this.GetControl("GestureBorder");
+ var gestureBorder2 = this.GetControl("GestureBorder2");
+ var lastGesture = this.GetControl("LastGesture");
+ var resetGestures = this.GetControl
diff --git a/samples/MobileSandbox.Android/MainActivity.cs b/samples/MobileSandbox.Android/MainActivity.cs
index ac9242dd52..d65f0dec92 100644
--- a/samples/MobileSandbox.Android/MainActivity.cs
+++ b/samples/MobileSandbox.Android/MainActivity.cs
@@ -5,8 +5,8 @@ using Avalonia.Android;
namespace MobileSandbox.Android
{
- [Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
- public class MainActivity : AvaloniaActivity
+ [Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+ public class MainActivity : AvaloniaMainActivity
{
}
}
diff --git a/samples/MobileSandbox.Android/SplashActivity.cs b/samples/MobileSandbox.Android/SplashActivity.cs
index c26371d6fe..ced092554d 100644
--- a/samples/MobileSandbox.Android/SplashActivity.cs
+++ b/samples/MobileSandbox.Android/SplashActivity.cs
@@ -1,11 +1,11 @@
using Android.App;
using Android.Content;
-using Android.OS;
+using Avalonia.Android;
namespace MobileSandbox.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
- public class SplashActivity : Activity
+ public class SplashActivity : AvaloniaSplashActivity
{
protected override void OnResume()
{
diff --git a/samples/MobileSandbox/App.xaml b/samples/MobileSandbox/App.xaml
index f3210e8941..85c97c9dbe 100644
--- a/samples/MobileSandbox/App.xaml
+++ b/samples/MobileSandbox/App.xaml
@@ -1,6 +1,5 @@
diff --git a/samples/MobileSandbox/MainView.xaml b/samples/MobileSandbox/MainView.xaml
index 9c46f3eae9..1eab13aa75 100644
--- a/samples/MobileSandbox/MainView.xaml
+++ b/samples/MobileSandbox/MainView.xaml
@@ -1,8 +1,11 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mobileSandbox="using:MobileSandbox"
+ x:DataType="mobileSandbox:MainView">
+
diff --git a/samples/MobileSandbox/Views/CustomNotificationView.xaml b/samples/MobileSandbox/Views/CustomNotificationView.xaml
index 29033ca5df..f07116583c 100644
--- a/samples/MobileSandbox/Views/CustomNotificationView.xaml
+++ b/samples/MobileSandbox/Views/CustomNotificationView.xaml
@@ -7,12 +7,12 @@
-
+
-
-
+
+
-
+
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index 823a0fbbef..20cc6c43e1 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -1,9 +1,11 @@
diff --git a/samples/RenderDemo/Pages/AnimationsPage.xaml b/samples/RenderDemo/Pages/AnimationsPage.xaml
index 9043bac33e..3f89a9d5f7 100644
--- a/samples/RenderDemo/Pages/AnimationsPage.xaml
+++ b/samples/RenderDemo/Pages/AnimationsPage.xaml
@@ -1,7 +1,9 @@
diff --git a/samples/RenderDemo/Pages/CustomAnimatorPage.xaml b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml
index b386636cae..0c625b6a77 100644
--- a/samples/RenderDemo/Pages/CustomAnimatorPage.xaml
+++ b/samples/RenderDemo/Pages/CustomAnimatorPage.xaml
@@ -1,7 +1,7 @@
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml b/samples/RenderDemo/Pages/GlyphRunPage.xaml
index 7db58e5286..e267b458bd 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:RenderDemo.Pages"
+ xmlns:local="using:RenderDemo.Pages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="RenderDemo.Pages.GlyphRunPage">
diff --git a/samples/RenderDemo/Pages/Transform3DPage.axaml b/samples/RenderDemo/Pages/Transform3DPage.axaml
index 30ed35bbac..7f3636648c 100644
--- a/samples/RenderDemo/Pages/Transform3DPage.axaml
+++ b/samples/RenderDemo/Pages/Transform3DPage.axaml
@@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:viewModels="using:RenderDemo.ViewModels"
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="700"
- x:Class="RenderDemo.Pages.Transform3DPage">
+ x:Class="RenderDemo.Pages.Transform3DPage"
+ x:DataType="viewModels:Transform3DPageViewModel">
diff --git a/samples/RenderDemo/Pages/TransitionsPage.xaml b/samples/RenderDemo/Pages/TransitionsPage.xaml
index 71b6ea0713..006c2eb20b 100644
--- a/samples/RenderDemo/Pages/TransitionsPage.xaml
+++ b/samples/RenderDemo/Pages/TransitionsPage.xaml
@@ -1,7 +1,9 @@
diff --git a/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml b/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
index fbc51414e3..f36b79224a 100644
--- a/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
+++ b/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
@@ -194,7 +194,7 @@
VerticalAlignment="Center"
Classes="h1"
Margin="{StaticResource HeaderMarginExpandedPane}"
- Text="{Binding $parent[TabControl].SelectedItem.Header, FallbackValue=''}">
+ Text="{Binding $parent[TabControl].SelectedItem.(TabItem.Header), FallbackValue=''}">
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml b/src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml
index c404a5c382..0d2e739b2b 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml
@@ -1,9 +1,10 @@
+ xmlns:controls="using:Avalonia.Diagnostics.Controls"
+ xmlns:converters="using:Avalonia.Diagnostics.Converters"
+ xmlns:viewModels="using:Avalonia.Diagnostics.ViewModels"
+ x:DataType="viewModels:ControlLayoutViewModel">
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml
index 35c9e27f1a..97e21079c1 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml
@@ -1,7 +1,9 @@
+ xmlns:views="using:Avalonia.Diagnostics.Views"
+ xmlns:viewModels="using:Avalonia.Diagnostics.ViewModels"
+ x:Class="Avalonia.Diagnostics.Views.MainView"
+ x:DataType="viewModels:MainViewModel">
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
index c6980bf97d..3ce4730698 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml
@@ -1,8 +1,7 @@
+ xmlns:sys="using:System"
+ xmlns:converters="using:Avalonia.Controls.Converters">
@@ -71,7 +70,6 @@
-
diff --git a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
index 7042f51c71..9c66ea9b84 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
@@ -1,7 +1,7 @@
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
index d1aee7ee9a..06b6cf30c2 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
@@ -1,7 +1,7 @@
+ xmlns:sys="using:System">
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
index dd2692cc5a..6a57cfacd0 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
@@ -1,7 +1,7 @@
+ xmlns:sys="using:System">
@@ -58,7 +56,7 @@
-
+
-
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
index c91e008e02..71ae012289 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
@@ -83,14 +83,14 @@
-
-
-
diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
index 4aa0ddc23a..24d9d21df8 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
@@ -1,6 +1,6 @@
+ xmlns:sys="using:System">
diff --git a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
index a4055519b6..7d45d0444f 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
@@ -1,8 +1,7 @@
+ xmlns:collections="using:System.Collections">
@@ -99,7 +98,7 @@
-
+
+ xmlns:sys="using:System">
@@ -28,7 +27,6 @@
- 0,0,0,4
40
40
41
@@ -84,18 +82,8 @@
-
-
-
+
+
diff --git a/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml b/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml
index 9798e5290b..57d6eabea4 100644
--- a/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml
@@ -1,6 +1,5 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ xmlns:sys="using:System">
diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml
index d9acd0d25a..f022746bf5 100644
--- a/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml
@@ -1,7 +1,7 @@
@@ -162,7 +162,7 @@
-
+
-
-
-
diff --git a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
index b4cf6313a6..5c57240aea 100644
--- a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
@@ -7,8 +7,7 @@
+ xmlns:sys="using:System">
@@ -30,7 +29,6 @@
- 0,0,0,4
40
40
41
@@ -91,19 +89,9 @@
-
+ Margin="{TemplateBinding Padding}">
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
diff --git a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml
index 3416b5406e..61dae9b445 100644
--- a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml
@@ -1,6 +1,7 @@
+ xmlns:dialogs="using:Avalonia.Dialogs"
+ xmlns:internal="using:Avalonia.Dialogs.Internal">
-
+
-
+
-
+
-
-
+
@@ -179,7 +180,7 @@
-
+
diff --git a/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml b/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml
index 8c51ec8609..ba1b35e2ee 100644
--- a/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml
@@ -1,26 +1,25 @@
-
+ xmlns:default="using:Avalonia.Themes.Simple">
-
diff --git a/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml b/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml
index 5adb5bde7e..3eb158d5b6 100644
--- a/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml
@@ -1,6 +1,6 @@
+ xmlns:converters="using:Avalonia.Controls.Converters">
diff --git a/src/Avalonia.Themes.Simple/Controls/RichTextBlock.xaml b/src/Avalonia.Themes.Simple/Controls/RichTextBlock.xaml
deleted file mode 100644
index c0570282cb..0000000000
--- a/src/Avalonia.Themes.Simple/Controls/RichTextBlock.xaml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml b/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml
new file mode 100644
index 0000000000..aaa6448aea
--- /dev/null
+++ b/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml b/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml
index 644c6ed416..4aefa0136c 100644
--- a/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml
@@ -64,7 +64,7 @@
-
+
diff --git a/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml b/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml
index f0d22aac97..3c621a981d 100644
--- a/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml
@@ -1,6 +1,5 @@
@@ -212,7 +213,8 @@
+ Theme="{StaticResource SimplePasswordBoxRevealButtonTheme}"
+ ClipToBounds="True" />
diff --git a/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml b/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml
index e02e3d8194..58066bb9a5 100644
--- a/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml
@@ -7,8 +7,7 @@
+ xmlns:sys="using:System">
@@ -33,7 +32,6 @@
40
1
1
- 0,0,0,4
40
41
242
@@ -90,20 +88,8 @@
-
-
+ Margin="{TemplateBinding Padding}">
-
-
diff --git a/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml b/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml
index 8b3452244c..6ca3262419 100644
--- a/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml
@@ -1,6 +1,6 @@
+ xmlns:converters="using:Avalonia.Controls.Converters">
diff --git a/src/Avalonia.Themes.Simple/IBitmapToImageConverter.cs b/src/Avalonia.Themes.Simple/IBitmapToImageConverter.cs
index fade026b51..d5bf003288 100644
--- a/src/Avalonia.Themes.Simple/IBitmapToImageConverter.cs
+++ b/src/Avalonia.Themes.Simple/IBitmapToImageConverter.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Themes.Simple
{
internal class IBitmapToImageConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value != null && value is IBitmap bm)
return new Image { Source=bm };
@@ -20,7 +20,7 @@ namespace Avalonia.Themes.Simple
return null;
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
diff --git a/src/Avalonia.Themes.Simple/InverseBooleanValueConverter.cs b/src/Avalonia.Themes.Simple/InverseBooleanValueConverter.cs
deleted file mode 100644
index 15cc5b4a80..0000000000
--- a/src/Avalonia.Themes.Simple/InverseBooleanValueConverter.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Globalization;
-using Avalonia.Data.Converters;
-
-namespace Avalonia.Themes.Simple
-{
- class InverseBooleanValueConverter : IValueConverter
- {
- public bool Default { get; set; }
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value is bool b ? !b : Default;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value is bool b ? !b : !Default;
- }
- }
-}
diff --git a/src/Avalonia.Themes.Simple/SimpleTheme.cs b/src/Avalonia.Themes.Simple/SimpleTheme.cs
deleted file mode 100644
index f225cb4c4d..0000000000
--- a/src/Avalonia.Themes.Simple/SimpleTheme.cs
+++ /dev/null
@@ -1,166 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-using Avalonia.Markup.Xaml.Styling;
-using Avalonia.Styling;
-#nullable enable
-
-namespace Avalonia.Themes.Simple
-{
- public class SimpleTheme : AvaloniaObject, IStyle, IResourceProvider
- {
- public static readonly StyledProperty ModeProperty =
- AvaloniaProperty.Register(nameof(Mode));
-
- private readonly Uri _baseUri;
- private bool _isLoading;
- private IStyle? _loaded;
- private Styles _sharedStyles = new();
- private Styles _simpleDark = new();
- private Styles _simpleLight = new();
- ///
- /// Initializes a new instance of the class.
- ///
- /// The base URL for the XAML context.
- public SimpleTheme(Uri? baseUri = null)
- {
- _baseUri = baseUri ?? new Uri("avares://Avalonia.Themes.Simple/");
- InitStyles(_baseUri);
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The XAML service provider.
- public SimpleTheme(IServiceProvider serviceProvider)
- {
- var service = serviceProvider.GetService(typeof(IUriContext));
- if (service == null)
- {
- throw new Exception("There is no service object of type IUriContext!");
- }
- _baseUri = ((IUriContext)service).BaseUri;
- InitStyles(_baseUri);
- }
-
- public event EventHandler? OwnerChanged
- {
- add
- {
- if (Loaded is IResourceProvider rp)
- {
- rp.OwnerChanged += value;
- }
- }
- remove
- {
- if (Loaded is IResourceProvider rp)
- {
- rp.OwnerChanged -= value;
- }
- }
- }
-
- IReadOnlyList IStyle.Children => _loaded?.Children ?? Array.Empty();
-
- bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false;
-
- public IStyle Loaded
- {
- get
- {
- if (_loaded == null)
- {
- _isLoading = true;
-
- if (Mode == SimpleThemeMode.Light)
- {
- _loaded = new Styles { _sharedStyles, _simpleLight };
- }
- else if (Mode == SimpleThemeMode.Dark)
- {
- _loaded = new Styles { _sharedStyles, _simpleDark };
- }
- _isLoading = false;
- }
-
- return _loaded!;
- }
- }
-
- ///
- /// Gets or sets the mode of the fluent theme (light, dark).
- ///
- public SimpleThemeMode Mode
- {
- get => GetValue(ModeProperty);
- set => SetValue(ModeProperty, value);
- }
- public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
-
- void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner);
-
- void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner);
-
- public SelectorMatchResult TryAttach(IStyleable target, object? host) => Loaded.TryAttach(target, host);
-
- public bool TryGetResource(object key, out object? value)
- {
- if (!_isLoading && Loaded is IResourceProvider p)
- {
- return p.TryGetResource(key, out value);
- }
-
- value = null;
- return false;
- }
-
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
- {
- base.OnPropertyChanged(change);
- if (change.Property == ModeProperty)
- {
- if (Mode == SimpleThemeMode.Dark)
- {
- (Loaded as Styles)![1] = _simpleDark[0];
- }
- else
- {
- (Loaded as Styles)![1] = _simpleLight[0];
- }
- }
- }
-
- private void InitStyles(Uri baseUri)
- {
- _sharedStyles = new Styles
- {
- new StyleInclude(baseUri)
- {
- Source = new Uri("avares://Avalonia.Themes.Simple/Controls/SimpleControls.xaml")
- },
- new StyleInclude(baseUri)
- {
- Source = new Uri("avares://Avalonia.Themes.Simple/Accents/Base.xaml")
- }
- };
- _simpleLight = new Styles
- {
- new StyleInclude(baseUri)
- {
- Source = new Uri("avares://Avalonia.Themes.Simple/Accents/BaseLight.xaml")
- }
- };
-
- _simpleDark = new Styles
- {
- new StyleInclude(baseUri)
- {
- Source = new Uri("avares://Avalonia.Themes.Simple/Accents/BaseDark.xaml")
- }
- };
- }
-
- }
-}
diff --git a/src/Avalonia.Themes.Simple/SimpleTheme.xaml b/src/Avalonia.Themes.Simple/SimpleTheme.xaml
new file mode 100644
index 0000000000..fe296bd288
--- /dev/null
+++ b/src/Avalonia.Themes.Simple/SimpleTheme.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs b/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs
new file mode 100644
index 0000000000..af9d305043
--- /dev/null
+++ b/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Styling;
+
+namespace Avalonia.Themes.Simple
+{
+ public class SimpleTheme : Styles
+ {
+ public static readonly StyledProperty ModeProperty =
+ AvaloniaProperty.Register(nameof(Mode));
+
+ private readonly IResourceDictionary _simpleDark;
+ private readonly IResourceDictionary _simpleLight;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SimpleTheme()
+ {
+ AvaloniaXamlLoader.Load(this);
+
+ _simpleDark = (IResourceDictionary)GetAndRemove("BaseDark");
+ _simpleLight = (IResourceDictionary)GetAndRemove("BaseLight");
+ EnsureThemeVariant();
+
+ object GetAndRemove(string key)
+ {
+ var val = Resources[key]
+ ?? throw new KeyNotFoundException($"Key {key} was not found in the resources");
+ Resources.Remove(key);
+ return val;
+ }
+ }
+
+ ///
+ /// Gets or sets the mode of the fluent theme (light, dark).
+ ///
+ public SimpleThemeMode Mode
+ {
+ get => GetValue(ModeProperty);
+ set => SetValue(ModeProperty, value);
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == ModeProperty)
+ {
+ EnsureThemeVariant();
+ }
+ }
+
+ private void EnsureThemeVariant()
+ {
+ var themeVariantResource = Mode == SimpleThemeMode.Dark ? _simpleDark : _simpleLight;
+ var dict = Resources.MergedDictionaries;
+ if (dict.Count == 1)
+ {
+ dict.Add(themeVariantResource);
+ }
+ else
+ {
+ dict[1] = themeVariantResource;
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.X11/Stubs.cs b/src/Avalonia.X11/Stubs.cs
deleted file mode 100644
index f73512f1e8..0000000000
--- a/src/Avalonia.X11/Stubs.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using Avalonia.Platform;
-
-namespace Avalonia.X11
-{
- class PlatformSettingsStub : IPlatformSettings
- {
- public Size DoubleClickSize { get; } = new Size(2, 2);
- public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
- ///
- public Size TouchDoubleClickSize => new Size(16, 16);
-
- ///
- public TimeSpan TouchDoubleClickTime => DoubleClickTime;
- }
-}
diff --git a/src/Avalonia.X11/X11Atoms.cs b/src/Avalonia.X11/X11Atoms.cs
index 424db94e0a..b00879bd1d 100644
--- a/src/Avalonia.X11/X11Atoms.cs
+++ b/src/Avalonia.X11/X11Atoms.cs
@@ -17,7 +17,7 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2006 Novell, Inc. (https://www.novell.com)
//
//
diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs
index 381cdd74c3..96dc16e186 100644
--- a/src/Avalonia.X11/X11Platform.cs
+++ b/src/Avalonia.X11/X11Platform.cs
@@ -80,7 +80,7 @@ namespace Avalonia.X11
.Bind().ToFunc(() => KeyboardDevice)
.Bind().ToConstant(new X11CursorFactory(Display))
.Bind().ToConstant(new X11Clipboard(this))
- .Bind().ToConstant(new PlatformSettingsStub())
+ .Bind().ToSingleton()
.Bind().ToConstant(new X11IconLoader())
.Bind().ToConstant(new LinuxMountedVolumeInfoProvider())
.Bind().ToConstant(new X11PlatformLifetimeEvents(this));
diff --git a/src/Avalonia.X11/X11Screens.cs b/src/Avalonia.X11/X11Screens.cs
index bcaafb6a53..ba6029b350 100644
--- a/src/Avalonia.X11/X11Screens.cs
+++ b/src/Avalonia.X11/X11Screens.cs
@@ -9,7 +9,7 @@ using JetBrains.Annotations;
namespace Avalonia.X11
{
- class X11Screens : IScreenImpl
+ class X11Screens : IScreenImpl
{
private IX11Screens _impl;
@@ -218,7 +218,7 @@ namespace Avalonia.X11
public int ScreenCount => _impl.Screens.Length;
public IReadOnlyList AllScreens =>
- _impl.Screens.Select(s => new Screen(s.PixelDensity, s.Bounds, s.WorkingArea, s.Primary)).ToArray();
+ _impl.Screens.Select(s => new Screen(s.Scaling, s.Bounds, s.WorkingArea, s.IsPrimary)).ToArray();
}
interface IX11Screens
@@ -281,30 +281,34 @@ namespace Avalonia.X11
{
private const int FullHDWidth = 1920;
private const int FullHDHeight = 1080;
- public bool Primary { get; }
+ public bool IsPrimary { get; }
public string Name { get; set; }
public PixelRect Bounds { get; set; }
public Size? PhysicalSize { get; set; }
- public double PixelDensity { get; set; }
+ public double Scaling { get; set; }
public PixelRect WorkingArea { get; set; }
- public X11Screen(PixelRect bounds, bool primary,
- string name, Size? physicalSize, double? pixelDensity)
+ public X11Screen(
+ PixelRect bounds,
+ bool isPrimary,
+ string name,
+ Size? physicalSize,
+ double? scaling)
{
- Primary = primary;
+ IsPrimary = isPrimary;
Name = name;
Bounds = bounds;
- if (physicalSize == null && pixelDensity == null)
+ if (physicalSize == null && scaling == null)
{
- PixelDensity = 1;
+ Scaling = 1;
}
- else if (pixelDensity == null)
+ else if (scaling == null)
{
- PixelDensity = GuessPixelDensity(bounds, physicalSize.Value);
+ Scaling = GuessPixelDensity(bounds, physicalSize.Value);
}
else
{
- PixelDensity = pixelDensity.Value;
+ Scaling = scaling.Value;
PhysicalSize = physicalSize;
}
}
diff --git a/src/Avalonia.X11/X11Structs.cs b/src/Avalonia.X11/X11Structs.cs
index 23abd31b2c..3f0a6aeb67 100644
--- a/src/Avalonia.X11/X11Structs.cs
+++ b/src/Avalonia.X11/X11Structs.cs
@@ -661,7 +661,7 @@ namespace Avalonia.X11 {
Type type = ev.GetType ();
FieldInfo [] fields = type.GetFields (System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance);
for (int i = 0; i < fields.Length; i++) {
- if (result != string.Empty) {
+ if (!string.IsNullOrEmpty(result)) {
result += ", ";
}
object value = fields [i].GetValue (ev);
diff --git a/src/Avalonia.X11/X11Window.Ime.cs b/src/Avalonia.X11/X11Window.Ime.cs
index d68feaca78..ca987d0a07 100644
--- a/src/Avalonia.X11/X11Window.Ime.cs
+++ b/src/Avalonia.X11/X11Window.Ime.cs
@@ -8,6 +8,7 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Platform.Interop;
+using JetBrains.Annotations;
using static Avalonia.X11.XLib;
namespace Avalonia.X11
@@ -104,13 +105,18 @@ namespace Avalonia.X11
if (ev.KeyEvent.state.HasAllFlags(XModifierMask.Mod2Mask)
&& key > X11Key.Num_Lock && key <= X11Key.KP_9)
key = (X11Key)XKeycodeToKeysym(_x11.Display, ev.KeyEvent.keycode, index ? 0 : 1).ToInt32();
-
- var filtered = ScheduleKeyInput(new RawKeyEventArgs(_keyboard, (ulong)ev.KeyEvent.time.ToInt64(), _inputRoot,
- ev.type == XEventName.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
- X11KeyTransform.ConvertKey(key), TranslateModifiers(ev.KeyEvent.state)), ref ev, (int)key, ev.KeyEvent.keycode);
-
- if (ev.type == XEventName.KeyPress && !filtered)
- TriggerClassicTextInputEvent(ref ev);
+
+ var convertedKey = X11KeyTransform.ConvertKey(key);
+ var modifiers = TranslateModifiers(ev.KeyEvent.state);
+ var timestamp = (ulong)ev.KeyEvent.time.ToInt64();
+ RawKeyEventArgs args =
+ ev.type == XEventName.KeyPress
+ ? new RawKeyEventArgsWithText(_keyboard, timestamp, _inputRoot, RawKeyEventType.KeyDown,
+ convertedKey, modifiers, TranslateEventToString(ref ev))
+ : new RawKeyEventArgs(_keyboard, timestamp, _inputRoot, RawKeyEventType.KeyUp, convertedKey,
+ modifiers);
+
+ ScheduleKeyInput(args, ref ev, (int)key, ev.KeyEvent.keycode);
}
void TriggerClassicTextInputEvent(ref XEvent ev)
@@ -156,16 +162,15 @@ namespace Avalonia.X11
}
- bool ScheduleKeyInput(RawKeyEventArgs args, ref XEvent xev, int keyval, int keycode)
+ void ScheduleKeyInput(RawKeyEventArgs args, ref XEvent xev, int keyval, int keycode)
{
_x11.LastActivityTimestamp = xev.ButtonEvent.time;
- if (_imeControl != null && _imeControl.IsEnabled)
- {
- if (FilterIme(args, xev, keyval, keycode))
- return true;
- }
+
+ if (_imeControl is { IsEnabled: true }
+ && FilterIme(args, xev, keyval, keycode))
+ return;
+
ScheduleInput(args);
- return false;
}
bool FilterIme(RawKeyEventArgs args, XEvent xev, int keyval, int keycode)
@@ -190,11 +195,7 @@ namespace Avalonia.X11
{
var ev = _imeQueue.Dequeue();
if (_imeControl == null || !await _imeControl.HandleEventAsync(ev.args, ev.keyval, ev.keycode))
- {
ScheduleInput(ev.args);
- if (ev.args.Type == RawKeyEventType.KeyDown)
- TriggerClassicTextInputEvent(ref ev.xev);
- }
}
}
finally
@@ -202,5 +203,18 @@ namespace Avalonia.X11
_processingIme = false;
}
}
+
+ // This class is used to attach the text value of the key to an asynchronously dispatched KeyDown event
+ class RawKeyEventArgsWithText : RawKeyEventArgs
+ {
+ public RawKeyEventArgsWithText([NotNull] IKeyboardDevice device, ulong timestamp, [NotNull] IInputRoot root,
+ RawKeyEventType type, Key key, RawInputModifiers modifiers, string text) :
+ base(device, timestamp, root, type, key, modifiers)
+ {
+ Text = text;
+ }
+
+ public string Text { get; }
+ }
}
}
diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs
index f24c33cafa..0b5ae281f4 100644
--- a/src/Avalonia.X11/X11Window.cs
+++ b/src/Avalonia.X11/X11Window.cs
@@ -120,7 +120,7 @@ namespace Avalonia.X11
if (!_popup && Screen != null)
{
- var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
+ var monitor = Screen.AllScreens.OrderBy(x => x.Scaling)
.FirstOrDefault(m => m.Bounds.Contains(Position));
if (monitor != null)
@@ -190,7 +190,7 @@ namespace Avalonia.X11
UpdateMotifHints();
UpdateSizeHints(null);
- _rawEventGrouper = new RawEventGrouper(e => Input?.Invoke(e));
+ _rawEventGrouper = new RawEventGrouper(DispatchInput);
_transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals);
_transparencyHelper.SetTransparencyRequest(WindowTransparencyLevel.None);
@@ -570,9 +570,9 @@ namespace Avalonia.X11
newScaling = _scalingOverride.Value;
else
{
- var monitor = _platform.X11Screens.Screens.OrderBy(x => x.PixelDensity)
+ var monitor = _platform.X11Screens.Screens.OrderBy(x => x.Scaling)
.FirstOrDefault(m => m.Bounds.Contains(Position));
- newScaling = monitor?.PixelDensity ?? RenderScaling;
+ newScaling = monitor?.Scaling ?? RenderScaling;
}
if (RenderScaling != newScaling)
@@ -724,7 +724,13 @@ namespace Avalonia.X11
_x11.LastActivityTimestamp = xev.ButtonEvent.time;
ScheduleInput(args);
}
-
+
+ void DispatchInput(RawInputEventArgs args)
+ {
+ Input?.Invoke(args);
+ if (!args.Handled && args is RawKeyEventArgsWithText text && !string.IsNullOrWhiteSpace(text.Text))
+ Input?.Invoke(new RawTextInputEventArgs(_keyboard, args.Timestamp, _inputRoot, text.Text));
+ }
public void ScheduleXI2Input(RawInputEventArgs args)
{
@@ -994,7 +1000,7 @@ namespace Avalonia.X11
public IScreenImpl Screen => _platform.Screens;
- public Size MaxAutoSizeHint => _platform.X11Screens.Screens.Select(s => s.Bounds.Size.ToSize(s.PixelDensity))
+ public Size MaxAutoSizeHint => _platform.X11Screens.Screens.Select(s => s.Bounds.Size.ToSize(s.Scaling))
.OrderByDescending(x => x.Width + x.Height).FirstOrDefault();
diff --git a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
new file mode 100644
index 0000000000..4537f8d73e
--- /dev/null
+++ b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
@@ -0,0 +1,40 @@
+
+
+
+ net7.0
+ Avalonia.Browser.Blazor
+ _IncludeGeneratedAvaloniaStaticFiles;$(ResolveStaticWebAssetsInputsDependsOn)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AvaloniaWebAssets Include="$(MSBuildThisFileDirectory)../Avalonia.Browser/wwwroot/**/*.*" />
+
+
+
+
+
+
diff --git a/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
new file mode 100644
index 0000000000..2cc74273c0
--- /dev/null
+++ b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
@@ -0,0 +1,45 @@
+using System.Runtime.InteropServices.JavaScript;
+using System.Runtime.Versioning;
+using System.Threading.Tasks;
+using System;
+using Avalonia.Browser.Interop;
+using Avalonia.Controls.ApplicationLifetimes;
+using Microsoft.AspNetCore.Components;
+using Microsoft.AspNetCore.Components.Rendering;
+using BrowserView = Avalonia.Browser.AvaloniaView;
+
+namespace Avalonia.Browser.Blazor;
+
+[SupportedOSPlatform("browser")]
+public class AvaloniaView : ComponentBase
+{
+ private Browser.AvaloniaView? _browserView;
+ private readonly string _containerId;
+
+ public AvaloniaView()
+ {
+ _containerId = "av_container_" + Guid.NewGuid();
+ }
+
+ protected override void BuildRenderTree(RenderTreeBuilder builder)
+ {
+ builder.OpenElement(0, "div");
+ builder.AddAttribute(1, "id", _containerId);
+ builder.AddAttribute(2, "style", "width:100vw;height:100vh");
+ builder.CloseElement();
+ }
+
+ protected override async Task OnInitializedAsync()
+ {
+ if (OperatingSystem.IsBrowser())
+ {
+ await AvaloniaModule.ImportMain();
+
+ _browserView = new Browser.AvaloniaView(_containerId);
+ if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
+ {
+ _browserView.Content = lifetime.MainView;
+ }
+ }
+ }
+}
diff --git a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
new file mode 100644
index 0000000000..2432dc29a3
--- /dev/null
+++ b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
@@ -0,0 +1,39 @@
+using System.Runtime.Versioning;
+
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+
+namespace Avalonia.Browser.Blazor;
+
+[SupportedOSPlatform("browser")]
+public static class WebAppBuilder
+{
+ public static T SetupWithSingleViewLifetime(
+ this T builder)
+ where T : AppBuilderBase, new()
+ {
+ return builder.SetupWithLifetime(new BlazorSingleViewLifetime());
+ }
+
+ public static T UseBlazor(this T builder) where T : AppBuilderBase, new()
+ {
+ return builder
+ .UseBrowser()
+ .With(new BrowserPlatformOptions
+ {
+ FrameworkAssetPathResolver = new(filePath => $"/_content/Avalonia.Browser.Blazor/{filePath}")
+ });
+ }
+
+ public static AppBuilder Configure()
+ where TApp : Application, new()
+ {
+ return AppBuilder.Configure()
+ .UseBlazor();
+ }
+
+ internal class BlazorSingleViewLifetime : ISingleViewApplicationLifetime
+ {
+ public Control? MainView { get; set; }
+ }
+}
diff --git a/src/Web/Avalonia.Web/Avalonia.Web.csproj b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
similarity index 90%
rename from src/Web/Avalonia.Web/Avalonia.Web.csproj
rename to src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
index a4756a5e2b..2564140a03 100644
--- a/src/Web/Avalonia.Web/Avalonia.Web.csproj
+++ b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
@@ -7,6 +7,7 @@
+
@@ -39,10 +40,6 @@
-
-
-
-
@@ -52,4 +49,8 @@
+
+
+
+
diff --git a/src/Browser/Avalonia.Browser/Avalonia.Browser.props b/src/Browser/Avalonia.Browser/Avalonia.Browser.props
new file mode 100644
index 0000000000..668dd20789
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/Avalonia.Browser.props
@@ -0,0 +1,5 @@
+
+
+ 16384000
+
+
diff --git a/src/Browser/Avalonia.Browser/Avalonia.Browser.targets b/src/Browser/Avalonia.Browser/Avalonia.Browser.targets
new file mode 100644
index 0000000000..22363b33d8
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/Avalonia.Browser.targets
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ True
+ $(EmccExtraLDFlags) --js-library="$(MSBuildThisFileDirectory)\interop.js"
+ $(EmccExtraLDFlags) -sERROR_ON_UNDEFINED_SYMBOLS=0
+ true
+
+
+
+ true
+ full
+ true
+ -Oz
+ -Oz
+ false
+ false
+ 0
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+ en
+ false
+
+
diff --git a/src/Web/Avalonia.Web/AvaloniaView.cs b/src/Browser/Avalonia.Browser/AvaloniaView.cs
similarity index 79%
rename from src/Web/Avalonia.Web/AvaloniaView.cs
rename to src/Browser/Avalonia.Browser/AvaloniaView.cs
index e81620ffde..a407e1e4d8 100644
--- a/src/Web/Avalonia.Web/AvaloniaView.cs
+++ b/src/Browser/Avalonia.Browser/AvaloniaView.cs
@@ -1,5 +1,10 @@
using System;
+using System.Collections.Generic;
+using System.Reflection;
using System.Runtime.InteropServices.JavaScript;
+using Avalonia.Browser.Interop;
+using Avalonia.Browser.Skia;
+using Avalonia.Collections.Pooled;
using Avalonia.Controls;
using Avalonia.Controls.Embedding;
using Avalonia.Controls.Platform;
@@ -8,16 +13,14 @@ using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
-using Avalonia.Web.Interop;
-using Avalonia.Web.Skia;
-
using SkiaSharp;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
[System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
public partial class AvaloniaView : ITextInputMethodImpl
{
+ private static readonly PooledList s_intermediatePointsPooledList = new(ClearMode.Never);
private readonly BrowserTopLevelImpl _topLevelImpl;
private EmbeddableControlRoot _topLevel;
@@ -37,16 +40,14 @@ namespace Avalonia.Web
private bool _useGL;
private ITextInputMethodClient? _client;
- private static int _canvasCount;
public AvaloniaView(string divId)
+ : this(DomHelper.GetElementById(divId) ?? throw new Exception($"Element with id {divId} was not found in the html document."))
{
- var host = DomHelper.GetElementById(divId);
- if (host == null)
- {
- throw new Exception($"Element with id {divId} was not found in the html document.");
- }
+ }
+ public AvaloniaView(JSObject host)
+ {
var hostContent = DomHelper.CreateAvaloniaHost(host);
if (hostContent == null)
{
@@ -54,18 +55,16 @@ namespace Avalonia.Web
}
_containerElement = hostContent.GetPropertyAsJSObject("host")
- ?? throw new InvalidOperationException("Host cannot be null");
+ ?? throw new InvalidOperationException("Host cannot be null");
_canvas = hostContent.GetPropertyAsJSObject("canvas")
- ?? throw new InvalidOperationException("Canvas cannot be null");
+ ?? throw new InvalidOperationException("Canvas cannot be null");
_nativeControlsContainer = hostContent.GetPropertyAsJSObject("nativeHost")
- ?? throw new InvalidOperationException("NativeHost cannot be null");
+ ?? throw new InvalidOperationException("NativeHost cannot be null");
_inputElement = hostContent.GetPropertyAsJSObject("inputElement")
- ?? throw new InvalidOperationException("InputElement cannot be null");
+ ?? throw new InvalidOperationException("InputElement cannot be null");
_splash = DomHelper.GetElementById("avalonia-splash");
- _canvas.SetProperty("id", $"avaloniaCanvas{_canvasCount++}");
-
_topLevelImpl = new BrowserTopLevelImpl(this);
_topLevel = new WebEmbeddableControlRoot(_topLevelImpl, () =>
@@ -81,8 +80,7 @@ namespace Avalonia.Web
_topLevelImpl.SetCssCursor = (cursor) =>
{
- InputHelper.SetCursor(_containerElement, cursor); // macOS
- InputHelper.SetCursor(_canvas, cursor); // windows
+ InputHelper.SetCursor(_containerElement, cursor);
};
_topLevel.Prepare();
@@ -101,7 +99,8 @@ namespace Avalonia.Web
OnCompositionUpdate,
OnCompositionEnd);
- InputHelper.SubscribePointerEvents(_containerElement, OnPointerMove, OnPointerDown, OnPointerUp, OnWheel);
+ InputHelper.SubscribePointerEvents(_containerElement, OnPointerMove, OnPointerDown, OnPointerUp,
+ OnPointerCancel, OnWheel);
var skiaOptions = AvaloniaLocator.Current.GetService();
@@ -122,7 +121,12 @@ namespace Avalonia.Web
_context.SetResourceCacheLimit(skiaOptions?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
}
- _topLevelImpl.Surfaces = new[] { new BrowserSkiaSurface(_context, _jsGlInfo, ColorType, new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi, GRSurfaceOrigin.BottomLeft) };
+ _topLevelImpl.Surfaces = new[]
+ {
+ new BrowserSkiaSurface(_context, _jsGlInfo, ColorType,
+ new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi,
+ GRSurfaceOrigin.BottomLeft)
+ };
}
else
{
@@ -137,9 +141,11 @@ namespace Avalonia.Web
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
- DomHelper.ObserveSize(host, divId, OnSizeChanged);
+ DomHelper.ObserveSize(host, null, OnSizeChanged);
CanvasHelper.RequestAnimationFrame(_canvas, true);
+
+ InputHelper.FocusElement(_containerElement);
}
private static RawPointerPoint ExtractRawPointerFromJSArgs(JSObject args)
@@ -158,17 +164,36 @@ namespace Avalonia.Web
private bool OnPointerMove(JSObject args)
{
- var type = args.GetPropertyAsString("pointertype");
-
+ var pointerType = args.GetPropertyAsString("pointerType");
var point = ExtractRawPointerFromJSArgs(args);
+ var type = pointerType switch
+ {
+ "touch" => RawPointerEventType.TouchUpdate,
+ _ => RawPointerEventType.Move
+ };
+
+ var coalescedEvents = new Lazy?>(() =>
+ {
+ var points = InputHelper.GetCoalescedEvents(args);
+ s_intermediatePointsPooledList.Clear();
+ s_intermediatePointsPooledList.Capacity = points.Length - 1;
- return _topLevelImpl.RawPointerEvent(RawPointerEventType.Move, type!, point, GetModifiers(args), args.GetPropertyAsInt32("pointerId"));
+ // Skip the last one, as it is already processed point.
+ for (var i = 0; i < points.Length - 1; i++)
+ {
+ var point = points[i];
+ s_intermediatePointsPooledList.Add(ExtractRawPointerFromJSArgs(point));
+ }
+
+ return s_intermediatePointsPooledList;
+ });
+
+ return _topLevelImpl.RawPointerEvent(type, pointerType!, point, GetModifiers(args), args.GetPropertyAsInt32("pointerId"), coalescedEvents);
}
private bool OnPointerDown(JSObject args)
{
- var pointerType = args.GetPropertyAsString("pointerType");
-
+ var pointerType = args.GetPropertyAsString("pointerType") ?? "mouse";
var type = pointerType switch
{
"touch" => RawPointerEventType.TouchBegin,
@@ -179,20 +204,18 @@ namespace Avalonia.Web
2 => RawPointerEventType.RightButtonDown,
3 => RawPointerEventType.XButton1Down,
4 => RawPointerEventType.XButton2Down,
- // 5 => Pen eraser button,
+ 5 => RawPointerEventType.XButton1Down, // should be pen eraser button,
_ => RawPointerEventType.Move
}
};
var point = ExtractRawPointerFromJSArgs(args);
-
- return _topLevelImpl.RawPointerEvent(type, pointerType!, point, GetModifiers(args), args.GetPropertyAsInt32("pointerId"));
+ return _topLevelImpl.RawPointerEvent(type, pointerType, point, GetModifiers(args), args.GetPropertyAsInt32("pointerId"));
}
private bool OnPointerUp(JSObject args)
{
var pointerType = args.GetPropertyAsString("pointerType") ?? "mouse";
-
var type = pointerType switch
{
"touch" => RawPointerEventType.TouchEnd,
@@ -203,15 +226,27 @@ namespace Avalonia.Web
2 => RawPointerEventType.RightButtonUp,
3 => RawPointerEventType.XButton1Up,
4 => RawPointerEventType.XButton2Up,
- // 5 => Pen eraser button,
+ 5 => RawPointerEventType.XButton1Up, // should be pen eraser button,
_ => RawPointerEventType.Move
}
};
var point = ExtractRawPointerFromJSArgs(args);
-
return _topLevelImpl.RawPointerEvent(type, pointerType, point, GetModifiers(args), args.GetPropertyAsInt32("pointerId"));
}
+
+ private bool OnPointerCancel(JSObject args)
+ {
+ var pointerType = args.GetPropertyAsString("pointerType") ?? "mouse";
+ if (pointerType == "touch")
+ {
+ var point = ExtractRawPointerFromJSArgs(args);
+ _topLevelImpl.RawPointerEvent(RawPointerEventType.TouchCancel, pointerType, point,
+ GetModifiers(args), args.GetPropertyAsInt32("pointerId"));
+ }
+
+ return false;
+ }
private bool OnWheel(JSObject args)
{
@@ -256,7 +291,14 @@ namespace Avalonia.Web
private bool OnKeyDown (string code, string key, int modifier)
{
- return _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyDown, code, key, (RawInputModifiers)modifier);
+ var handled = _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyDown, code, key, (RawInputModifiers)modifier);
+
+ if (!handled && key.Length == 1)
+ {
+ handled = _topLevelImpl.RawTextEvent(key);
+ }
+
+ return handled;
}
private bool OnKeyUp(string code, string key, int modifier)
@@ -387,7 +429,7 @@ namespace Avalonia.Web
InputHelper.FocusElement(_containerElement);
}
- public void SetClient(ITextInputMethodClient? client)
+ void ITextInputMethodImpl.SetClient(ITextInputMethodClient? client)
{
Console.WriteLine("Set Client");
if (_client != null)
@@ -431,18 +473,18 @@ namespace Avalonia.Web
}
}
- public void SetCursorRect(Rect rect)
+ void ITextInputMethodImpl.SetCursorRect(Rect rect)
{
InputHelper.FocusElement(_inputElement);
InputHelper.SetBounds(_inputElement, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height, _client?.SurroundingText.CursorOffset ?? 0);
InputHelper.FocusElement(_inputElement);
}
- public void SetOptions(TextInputOptions options)
+ void ITextInputMethodImpl.SetOptions(TextInputOptions options)
{
}
- public void Reset()
+ void ITextInputMethodImpl.Reset()
{
InputHelper.ClearInputElement(_inputElement);
InputHelper.SetSurroundingText(_inputElement, "", 0, 0);
diff --git a/src/Web/Avalonia.Web/BrowserNativeControlHost.cs b/src/Browser/Avalonia.Browser/BrowserNativeControlHost.cs
similarity index 98%
rename from src/Web/Avalonia.Web/BrowserNativeControlHost.cs
rename to src/Browser/Avalonia.Browser/BrowserNativeControlHost.cs
index 4cdcf627e6..7e91d29019 100644
--- a/src/Web/Avalonia.Web/BrowserNativeControlHost.cs
+++ b/src/Browser/Avalonia.Browser/BrowserNativeControlHost.cs
@@ -1,12 +1,11 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices.JavaScript;
-
+using Avalonia.Browser.Interop;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
-using Avalonia.Web.Interop;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
internal class BrowserNativeControlHost : INativeControlHostImpl
{
diff --git a/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs b/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
new file mode 100644
index 0000000000..0abc7703da
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.JavaScript;
+using System.Text.RegularExpressions;
+using Avalonia.Browser.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Browser;
+
+internal class BrowserRuntimePlatform : StandardRuntimePlatform
+{
+ private static readonly Lazy Info = new(() =>
+ {
+ var result = new RuntimePlatformInfo
+ {
+ IsCoreClr = true, // WASM browser is always CoreCLR
+ IsBrowser = true, // BrowserRuntimePlatform only runs on Browser.
+ OperatingSystem = OperatingSystemType.Browser,
+ IsMobile = AvaloniaModule.IsMobile()
+ };
+
+ return result;
+ });
+
+ public override RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
+}
diff --git a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
new file mode 100644
index 0000000000..ee4f6eca9b
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
@@ -0,0 +1,54 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using System.Runtime.Versioning;
+using Avalonia.Browser.Skia;
+using Avalonia.Platform;
+
+namespace Avalonia.Browser;
+
+[SupportedOSPlatform("browser")]
+public class BrowserSingleViewLifetime : ISingleViewApplicationLifetime
+{
+ public AvaloniaView? View;
+
+ public Control? MainView
+ {
+ get => View!.Content;
+ set => View!.Content = value;
+ }
+}
+
+public class BrowserPlatformOptions
+{
+ public Func FrameworkAssetPathResolver { get; set; } = new(fileName => $"./{fileName}");
+}
+
+[SupportedOSPlatform("browser")]
+public static class WebAppBuilder
+{
+ public static T SetupBrowserApp(
+ this T builder, string mainDivId)
+ where T : AppBuilderBase, new()
+ {
+ var lifetime = new BrowserSingleViewLifetime();
+
+ return builder
+ .UseBrowser()
+ .AfterSetup(b =>
+ {
+ lifetime.View = new AvaloniaView(mainDivId);
+ })
+ .SetupWithLifetime(lifetime);
+ }
+
+ public static T UseBrowser(
+ this T builder)
+ where T : AppBuilderBase, new()
+ {
+ return builder
+ .UseWindowingSubsystem(BrowserWindowingPlatform.Register)
+ .UseSkia()
+ .With(new SkiaOptions { CustomGpuFactory = () => new BrowserSkiaGpu() });
+ }
+}
diff --git a/src/Web/Avalonia.Web/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
similarity index 94%
rename from src/Web/Avalonia.Web/BrowserTopLevelImpl.cs
rename to src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
index b955da6df2..69e2d27181 100644
--- a/src/Web/Avalonia.Web/BrowserTopLevelImpl.cs
+++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
@@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using Avalonia.Browser.Skia;
+using Avalonia.Browser.Storage;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
@@ -11,10 +13,8 @@ using Avalonia.Platform;
using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
-using Avalonia.Web.Skia;
-using Avalonia.Web.Storage;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
[System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
internal class BrowserTopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider
@@ -67,17 +67,22 @@ namespace Avalonia.Web
public bool RawPointerEvent(
RawPointerEventType eventType, string pointerType,
- RawPointerPoint p, RawInputModifiers modifiers, long touchPointId)
+ RawPointerPoint p, RawInputModifiers modifiers, long touchPointId,
+ Lazy?>? intermediatePoints = null)
{
if (_inputRoot is { }
&& Input is { } input)
{
var device = GetPointerDevice(pointerType);
var args = device is TouchDevice ?
- new RawTouchEventArgs(device, Timestamp, _inputRoot, eventType, p, modifiers, touchPointId) :
+ new RawTouchEventArgs(device, Timestamp, _inputRoot, eventType, p, modifiers, touchPointId)
+ {
+ IntermediatePoints = intermediatePoints
+ } :
new RawPointerEventArgs(device, Timestamp, _inputRoot, eventType, p, modifiers)
{
- RawPointerId = touchPointId
+ RawPointerId = touchPointId,
+ IntermediatePoints = intermediatePoints
};
input.Invoke(args);
diff --git a/src/Web/Avalonia.Web/ClipboardImpl.cs b/src/Browser/Avalonia.Browser/ClipboardImpl.cs
similarity index 92%
rename from src/Web/Avalonia.Web/ClipboardImpl.cs
rename to src/Browser/Avalonia.Browser/ClipboardImpl.cs
index 793099f55a..f24d607dae 100644
--- a/src/Web/Avalonia.Web/ClipboardImpl.cs
+++ b/src/Browser/Avalonia.Browser/ClipboardImpl.cs
@@ -1,10 +1,10 @@
using System;
using System.Threading.Tasks;
+using Avalonia.Browser.Interop;
using Avalonia.Input;
using Avalonia.Input.Platform;
-using Avalonia.Web.Interop;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
internal class ClipboardImpl : IClipboard
{
diff --git a/src/Web/Avalonia.Web/Cursor.cs b/src/Browser/Avalonia.Browser/Cursor.cs
similarity index 97%
rename from src/Web/Avalonia.Web/Cursor.cs
rename to src/Browser/Avalonia.Browser/Cursor.cs
index 5db0bdeda2..ec0dcc51b4 100644
--- a/src/Web/Avalonia.Web/Cursor.cs
+++ b/src/Browser/Avalonia.Browser/Cursor.cs
@@ -3,9 +3,9 @@ using System.IO;
using Avalonia.Input;
using Avalonia.Platform;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
- public class CssCursor : ICursorImpl
+ internal class CssCursor : ICursorImpl
{
public const string Default = "default";
public string? Value { get; set; }
diff --git a/src/Browser/Avalonia.Browser/Interop/AvaloniaModule.cs b/src/Browser/Avalonia.Browser/Interop/AvaloniaModule.cs
new file mode 100644
index 0000000000..b283fbaa56
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/Interop/AvaloniaModule.cs
@@ -0,0 +1,25 @@
+using System.Runtime.InteropServices.JavaScript;
+using System.Threading.Tasks;
+
+namespace Avalonia.Browser.Interop;
+
+internal static partial class AvaloniaModule
+{
+ public const string MainModuleName = "avalonia";
+ public const string StorageModuleName = "storage";
+
+ public static Task ImportMain()
+ {
+ var options = AvaloniaLocator.Current.GetService() ?? new BrowserPlatformOptions();
+ return JSHost.ImportAsync(MainModuleName, options.FrameworkAssetPathResolver("avalonia.js"));
+ }
+
+ public static Task ImportStorage()
+ {
+ var options = AvaloniaLocator.Current.GetService() ?? new BrowserPlatformOptions();
+ return JSHost.ImportAsync(StorageModuleName, options.FrameworkAssetPathResolver("storage.js"));
+ }
+
+ [JSImport("Caniuse.isMobile", AvaloniaModule.MainModuleName)]
+ public static partial bool IsMobile();
+}
diff --git a/src/Web/Avalonia.Web/Interop/CanvasHelper.cs b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
similarity index 82%
rename from src/Web/Avalonia.Web/Interop/CanvasHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
index 66a1d421b7..8321b00658 100644
--- a/src/Web/Avalonia.Web/Interop/CanvasHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
@@ -2,7 +2,7 @@
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.JavaScript;
-namespace Avalonia.Web.Interop;
+namespace Avalonia.Browser.Interop;
internal record GLInfo(int ContextId, uint FboId, int Stencils, int Samples, int Depth);
@@ -29,13 +29,13 @@ internal static partial class CanvasHelper
return glInfo;
}
- [JSImport("Canvas.requestAnimationFrame", "avalonia.ts")]
+ [JSImport("Canvas.requestAnimationFrame", AvaloniaModule.MainModuleName)]
public static partial void RequestAnimationFrame(JSObject canvas, bool renderLoop);
- [JSImport("Canvas.setCanvasSize", "avalonia.ts")]
- public static partial void SetCanvasSize(JSObject canvas, int height, int width);
+ [JSImport("Canvas.setCanvasSize", AvaloniaModule.MainModuleName)]
+ public static partial void SetCanvasSize(JSObject canvas, int width, int height);
- [JSImport("Canvas.initGL", "avalonia.ts")]
+ [JSImport("Canvas.initGL", AvaloniaModule.MainModuleName)]
private static partial JSObject InitGL(
JSObject canvas,
string canvasId,
diff --git a/src/Web/Avalonia.Web/Interop/DomHelper.cs b/src/Browser/Avalonia.Browser/Interop/DomHelper.cs
similarity index 67%
rename from src/Web/Avalonia.Web/Interop/DomHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/DomHelper.cs
index c02bc4dae3..b97a03209b 100644
--- a/src/Web/Avalonia.Web/Interop/DomHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/DomHelper.cs
@@ -1,27 +1,27 @@
using System;
using System.Runtime.InteropServices.JavaScript;
-namespace Avalonia.Web.Interop;
+namespace Avalonia.Browser.Interop;
internal static partial class DomHelper
{
[JSImport("globalThis.document.getElementById")]
internal static partial JSObject? GetElementById(string id);
- [JSImport("AvaloniaDOM.createAvaloniaHost", "avalonia.ts")]
+ [JSImport("AvaloniaDOM.createAvaloniaHost", AvaloniaModule.MainModuleName)]
public static partial JSObject CreateAvaloniaHost(JSObject element);
- [JSImport("AvaloniaDOM.addClass", "avalonia.ts")]
+ [JSImport("AvaloniaDOM.addClass", AvaloniaModule.MainModuleName)]
public static partial void AddCssClass(JSObject element, string className);
- [JSImport("SizeWatcher.observe", "avalonia.ts")]
+ [JSImport("SizeWatcher.observe", AvaloniaModule.MainModuleName)]
public static partial JSObject ObserveSize(
JSObject canvas,
- string canvasId,
+ string? canvasId,
[JSMarshalAs>]
Action onSizeChanged);
- [JSImport("DpiWatcher.start", "avalonia.ts")]
+ [JSImport("DpiWatcher.start", AvaloniaModule.MainModuleName)]
public static partial double ObserveDpi(
[JSMarshalAs>]
Action onDpiChanged);
diff --git a/src/Web/Avalonia.Web/Interop/InputHelper.cs b/src/Browser/Avalonia.Browser/Interop/InputHelper.cs
similarity index 67%
rename from src/Web/Avalonia.Web/Interop/InputHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/InputHelper.cs
index b32b6566f2..7a010dc782 100644
--- a/src/Web/Avalonia.Web/Interop/InputHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/InputHelper.cs
@@ -1,12 +1,13 @@
using System;
+using System.Runtime.InteropServices;
using System.Runtime.InteropServices.JavaScript;
using System.Threading.Tasks;
-namespace Avalonia.Web.Interop;
+namespace Avalonia.Browser.Interop;
internal static partial class InputHelper
{
- [JSImport("InputHelper.subscribeKeyEvents", "avalonia.ts")]
+ [JSImport("InputHelper.subscribeKeyEvents", AvaloniaModule.MainModuleName)]
public static partial void SubscribeKeyEvents(
JSObject htmlElement,
[JSMarshalAs>]
@@ -14,7 +15,7 @@ internal static partial class InputHelper
[JSMarshalAs>]
Func keyUp);
- [JSImport("InputHelper.subscribeTextEvents", "avalonia.ts")]
+ [JSImport("InputHelper.subscribeTextEvents", AvaloniaModule.MainModuleName)]
public static partial void SubscribeTextEvents(
JSObject htmlElement,
[JSMarshalAs>]
@@ -26,7 +27,7 @@ internal static partial class InputHelper
[JSMarshalAs>]
Func onCompositionEnd);
- [JSImport("InputHelper.subscribePointerEvents", "avalonia.ts")]
+ [JSImport("InputHelper.subscribePointerEvents", AvaloniaModule.MainModuleName)]
public static partial void SubscribePointerEvents(
JSObject htmlElement,
[JSMarshalAs>]
@@ -36,38 +37,43 @@ internal static partial class InputHelper
[JSMarshalAs>]
Func pointerUp,
[JSMarshalAs>]
+ Func pointerCancel,
+ [JSMarshalAs>]
Func wheel);
- [JSImport("InputHelper.subscribeInputEvents", "avalonia.ts")]
+ [JSImport("InputHelper.subscribeInputEvents", AvaloniaModule.MainModuleName)]
public static partial void SubscribeInputEvents(
JSObject htmlElement,
[JSMarshalAs>]
Func input);
+ [JSImport("InputHelper.getCoalescedEvents", AvaloniaModule.MainModuleName)]
+ [return: JSMarshalAs>]
+ public static partial JSObject[] GetCoalescedEvents(JSObject pointerEvent);
- [JSImport("InputHelper.clearInput", "avalonia.ts")]
+ [JSImport("InputHelper.clearInput", AvaloniaModule.MainModuleName)]
public static partial void ClearInputElement(JSObject htmlElement);
- [JSImport("InputHelper.isInputElement", "avalonia.ts")]
+ [JSImport("InputHelper.isInputElement", AvaloniaModule.MainModuleName)]
public static partial void IsInputElement(JSObject htmlElement);
- [JSImport("InputHelper.focusElement", "avalonia.ts")]
+ [JSImport("InputHelper.focusElement", AvaloniaModule.MainModuleName)]
public static partial void FocusElement(JSObject htmlElement);
- [JSImport("InputHelper.setCursor", "avalonia.ts")]
+ [JSImport("InputHelper.setCursor", AvaloniaModule.MainModuleName)]
public static partial void SetCursor(JSObject htmlElement, string kind);
- [JSImport("InputHelper.hide", "avalonia.ts")]
+ [JSImport("InputHelper.hide", AvaloniaModule.MainModuleName)]
public static partial void HideElement(JSObject htmlElement);
- [JSImport("InputHelper.show", "avalonia.ts")]
+ [JSImport("InputHelper.show", AvaloniaModule.MainModuleName)]
public static partial void ShowElement(JSObject htmlElement);
- [JSImport("InputHelper.setSurroundingText", "avalonia.ts")]
+ [JSImport("InputHelper.setSurroundingText", AvaloniaModule.MainModuleName)]
public static partial void SetSurroundingText(JSObject htmlElement, string text, int start, int end);
- [JSImport("InputHelper.setBounds", "avalonia.ts")]
+ [JSImport("InputHelper.setBounds", AvaloniaModule.MainModuleName)]
public static partial void SetBounds(JSObject htmlElement, int x, int y, int width, int height, int caret);
[JSImport("globalThis.navigator.clipboard.readText")]
diff --git a/src/Web/Avalonia.Web/Interop/NativeControlHostHelper.cs b/src/Browser/Avalonia.Browser/Interop/NativeControlHostHelper.cs
similarity index 53%
rename from src/Web/Avalonia.Web/Interop/NativeControlHostHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/NativeControlHostHelper.cs
index 5cc86bf622..a362be82d8 100644
--- a/src/Web/Avalonia.Web/Interop/NativeControlHostHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/NativeControlHostHelper.cs
@@ -1,28 +1,28 @@
using System;
using System.Runtime.InteropServices.JavaScript;
-namespace Avalonia.Web.Interop;
+namespace Avalonia.Browser.Interop;
internal static partial class NativeControlHostHelper
{
- [JSImport("NativeControlHost.createDefaultChild", "avalonia.ts")]
+ [JSImport("NativeControlHost.createDefaultChild", AvaloniaModule.MainModuleName)]
internal static partial JSObject CreateDefaultChild(JSObject? parent);
- [JSImport("NativeControlHost.createAttachment", "avalonia.ts")]
+ [JSImport("NativeControlHost.createAttachment", AvaloniaModule.MainModuleName)]
internal static partial JSObject CreateAttachment();
- [JSImport("NativeControlHost.initializeWithChildHandle", "avalonia.ts")]
+ [JSImport("NativeControlHost.initializeWithChildHandle", AvaloniaModule.MainModuleName)]
internal static partial void InitializeWithChildHandle(JSObject element, JSObject child);
- [JSImport("NativeControlHost.attachTo", "avalonia.ts")]
+ [JSImport("NativeControlHost.attachTo", AvaloniaModule.MainModuleName)]
internal static partial void AttachTo(JSObject element, JSObject? host);
- [JSImport("NativeControlHost.showInBounds", "avalonia.ts")]
+ [JSImport("NativeControlHost.showInBounds", AvaloniaModule.MainModuleName)]
internal static partial void ShowInBounds(JSObject element, double x, double y, double width, double height);
- [JSImport("NativeControlHost.hideWithSize", "avalonia.ts")]
+ [JSImport("NativeControlHost.hideWithSize", AvaloniaModule.MainModuleName)]
internal static partial void HideWithSize(JSObject element, double width, double height);
- [JSImport("NativeControlHost.releaseChild", "avalonia.ts")]
+ [JSImport("NativeControlHost.releaseChild", AvaloniaModule.MainModuleName)]
internal static partial void ReleaseChild(JSObject element);
}
diff --git a/src/Web/Avalonia.Web/Interop/StorageHelper.cs b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
similarity index 54%
rename from src/Web/Avalonia.Web/Interop/StorageHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
index 4dc55fd959..c44af810d1 100644
--- a/src/Web/Avalonia.Web/Interop/StorageHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
@@ -1,55 +1,55 @@
using System.Runtime.InteropServices.JavaScript;
using System.Threading.Tasks;
-namespace Avalonia.Web.Interop;
+namespace Avalonia.Browser.Interop;
internal static partial class StorageHelper
{
- [JSImport("Caniuse.canShowOpenFilePicker", "avalonia.ts")]
+ [JSImport("Caniuse.canShowOpenFilePicker", AvaloniaModule.MainModuleName)]
public static partial bool CanShowOpenFilePicker();
- [JSImport("Caniuse.canShowSaveFilePicker", "avalonia.ts")]
+ [JSImport("Caniuse.canShowSaveFilePicker", AvaloniaModule.MainModuleName)]
public static partial bool CanShowSaveFilePicker();
- [JSImport("Caniuse.canShowDirectoryPicker", "avalonia.ts")]
+ [JSImport("Caniuse.canShowDirectoryPicker", AvaloniaModule.MainModuleName)]
public static partial bool CanShowDirectoryPicker();
- [JSImport("StorageProvider.selectFolderDialog", "storage.ts")]
+ [JSImport("StorageProvider.selectFolderDialog", AvaloniaModule.StorageModuleName)]
public static partial Task SelectFolderDialog(JSObject? startIn);
- [JSImport("StorageProvider.openFileDialog", "storage.ts")]
+ [JSImport("StorageProvider.openFileDialog", AvaloniaModule.StorageModuleName)]
public static partial Task OpenFileDialog(JSObject? startIn, bool multiple,
[JSMarshalAs>] object[]? types, bool excludeAcceptAllOption);
- [JSImport("StorageProvider.saveFileDialog", "storage.ts")]
+ [JSImport("StorageProvider.saveFileDialog", AvaloniaModule.StorageModuleName)]
public static partial Task SaveFileDialog(JSObject? startIn, string? suggestedName,
[JSMarshalAs>] object[]? types, bool excludeAcceptAllOption);
- [JSImport("StorageProvider.openBookmark", "storage.ts")]
+ [JSImport("StorageProvider.openBookmark", AvaloniaModule.StorageModuleName)]
public static partial Task OpenBookmark(string key);
- [JSImport("StorageItem.saveBookmark", "storage.ts")]
+ [JSImport("StorageItem.saveBookmark", AvaloniaModule.StorageModuleName)]
public static partial Task SaveBookmark(JSObject item);
- [JSImport("StorageItem.deleteBookmark", "storage.ts")]
+ [JSImport("StorageItem.deleteBookmark", AvaloniaModule.StorageModuleName)]
public static partial Task DeleteBookmark(JSObject item);
- [JSImport("StorageItem.getProperties", "storage.ts")]
+ [JSImport("StorageItem.getProperties", AvaloniaModule.StorageModuleName)]
public static partial Task GetProperties(JSObject item);
- [JSImport("StorageItem.openWrite", "storage.ts")]
+ [JSImport("StorageItem.openWrite", AvaloniaModule.StorageModuleName)]
public static partial Task OpenWrite(JSObject item);
- [JSImport("StorageItem.openRead", "storage.ts")]
+ [JSImport("StorageItem.openRead", AvaloniaModule.StorageModuleName)]
public static partial Task OpenRead(JSObject item);
- [JSImport("StorageItem.getItems", "storage.ts")]
+ [JSImport("StorageItem.getItems", AvaloniaModule.StorageModuleName)]
[return: JSMarshalAs>]
public static partial Task GetItems(JSObject item);
- [JSImport("StorageItems.itemsArray", "storage.ts")]
+ [JSImport("StorageItems.itemsArray", AvaloniaModule.StorageModuleName)]
public static partial JSObject[] ItemsArray(JSObject item);
- [JSImport("StorageProvider.createAcceptType", "storage.ts")]
+ [JSImport("StorageProvider.createAcceptType", AvaloniaModule.StorageModuleName)]
public static partial JSObject CreateAcceptType(string description, string[] mimeTypes);
}
diff --git a/src/Web/Avalonia.Web/Interop/StreamHelper.cs b/src/Browser/Avalonia.Browser/Interop/StreamHelper.cs
similarity index 69%
rename from src/Web/Avalonia.Web/Interop/StreamHelper.cs
rename to src/Browser/Avalonia.Browser/Interop/StreamHelper.cs
index 0a83bbb871..46fa671779 100644
--- a/src/Web/Avalonia.Web/Interop/StreamHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/StreamHelper.cs
@@ -2,33 +2,33 @@
using System.Runtime.InteropServices.JavaScript;
using System.Threading.Tasks;
-namespace Avalonia.Web.Storage;
+namespace Avalonia.Browser.Interop;
///
/// Set of FileSystemWritableFileStream and Blob methods.
///
internal static partial class StreamHelper
{
- [JSImport("StreamHelper.seek", "avalonia.ts")]
+ [JSImport("StreamHelper.seek", AvaloniaModule.MainModuleName)]
public static partial void Seek(JSObject stream, [JSMarshalAs] long position);
- [JSImport("StreamHelper.truncate", "avalonia.ts")]
+ [JSImport("StreamHelper.truncate", AvaloniaModule.MainModuleName)]
public static partial void Truncate(JSObject stream, [JSMarshalAs] long size);
- [JSImport("StreamHelper.write", "avalonia.ts")]
+ [JSImport("StreamHelper.write", AvaloniaModule.MainModuleName)]
public static partial Task WriteAsync(JSObject stream, [JSMarshalAs] ArraySegment data);
- [JSImport("StreamHelper.close", "avalonia.ts")]
+ [JSImport("StreamHelper.close", AvaloniaModule.MainModuleName)]
public static partial Task CloseAsync(JSObject stream);
- [JSImport("StreamHelper.byteLength", "avalonia.ts")]
+ [JSImport("StreamHelper.byteLength", AvaloniaModule.MainModuleName)]
[return: JSMarshalAs]
public static partial long ByteLength(JSObject stream);
- [JSImport("StreamHelper.sliceArrayBuffer", "avalonia.ts")]
+ [JSImport("StreamHelper.sliceArrayBuffer", AvaloniaModule.MainModuleName)]
private static partial Task SliceToArrayBuffer(JSObject stream, [JSMarshalAs] long offset, int count);
- [JSImport("StreamHelper.toMemoryView", "avalonia.ts")]
+ [JSImport("StreamHelper.toMemoryView", AvaloniaModule.MainModuleName)]
[return: JSMarshalAs>]
private static partial byte[] ArrayBufferToMemoryView(JSObject stream);
diff --git a/src/Web/Avalonia.Web/JSObjectControlHandle.cs b/src/Browser/Avalonia.Browser/JSObjectControlHandle.cs
similarity index 96%
rename from src/Web/Avalonia.Web/JSObjectControlHandle.cs
rename to src/Browser/Avalonia.Browser/JSObjectControlHandle.cs
index e56ca123eb..b0c8cecca6 100644
--- a/src/Web/Avalonia.Web/JSObjectControlHandle.cs
+++ b/src/Browser/Avalonia.Browser/JSObjectControlHandle.cs
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices.JavaScript;
using Avalonia.Controls.Platform;
-namespace Avalonia.Web;
+namespace Avalonia.Browser;
public class JSObjectControlHandle : INativeControlHostDestroyableControlHandle
{
diff --git a/src/Web/Avalonia.Web/Keycodes.cs b/src/Browser/Avalonia.Browser/Keycodes.cs
similarity index 99%
rename from src/Web/Avalonia.Web/Keycodes.cs
rename to src/Browser/Avalonia.Browser/Keycodes.cs
index d1185f6e45..5b6e3a329a 100644
--- a/src/Web/Avalonia.Web/Keycodes.cs
+++ b/src/Browser/Avalonia.Browser/Keycodes.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
using Avalonia.Input;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
internal static class Keycodes
{
diff --git a/src/Web/Avalonia.Web/ManualTriggerRenderTimer.cs b/src/Browser/Avalonia.Browser/ManualTriggerRenderTimer.cs
similarity index 81%
rename from src/Web/Avalonia.Web/ManualTriggerRenderTimer.cs
rename to src/Browser/Avalonia.Browser/ManualTriggerRenderTimer.cs
index 774848e19f..e9a314e823 100644
--- a/src/Web/Avalonia.Web/ManualTriggerRenderTimer.cs
+++ b/src/Browser/Avalonia.Browser/ManualTriggerRenderTimer.cs
@@ -2,9 +2,9 @@ using System;
using System.Diagnostics;
using Avalonia.Rendering;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
- public class ManualTriggerRenderTimer : IRenderTimer
+ internal class ManualTriggerRenderTimer : IRenderTimer
{
private static readonly Stopwatch s_sw = Stopwatch.StartNew();
diff --git a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpu.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpu.cs
similarity index 95%
rename from src/Web/Avalonia.Web/Skia/BrowserSkiaGpu.cs
rename to src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpu.cs
index f80838232b..a96ead93cb 100644
--- a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpu.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpu.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Avalonia.Skia;
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
public class BrowserSkiaGpu : ISkiaGpu
{
diff --git a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderSession.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderSession.cs
similarity index 96%
rename from src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderSession.cs
rename to src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderSession.cs
index a7f7d9db3d..81b37da7bd 100644
--- a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderSession.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderSession.cs
@@ -1,7 +1,7 @@
using Avalonia.Skia;
using SkiaSharp;
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
internal class BrowserSkiaGpuRenderSession : ISkiaGpuRenderSession
{
diff --git a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderTarget.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
similarity index 97%
rename from src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderTarget.cs
rename to src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
index dba9b34166..f69dd3c344 100644
--- a/src/Web/Avalonia.Web/Skia/BrowserSkiaGpuRenderTarget.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
@@ -1,7 +1,7 @@
using Avalonia.Skia;
using SkiaSharp;
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
internal class BrowserSkiaGpuRenderTarget : ISkiaGpuRenderTarget
{
diff --git a/src/Web/Avalonia.Web/Skia/BrowserSkiaRasterSurface.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaRasterSurface.cs
similarity index 98%
rename from src/Web/Avalonia.Web/Skia/BrowserSkiaRasterSurface.cs
rename to src/Browser/Avalonia.Browser/Skia/BrowserSkiaRasterSurface.cs
index c7005583ac..76b07a6827 100644
--- a/src/Web/Avalonia.Web/Skia/BrowserSkiaRasterSurface.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaRasterSurface.cs
@@ -5,7 +5,7 @@ using Avalonia.Platform;
using Avalonia.Skia;
using SkiaSharp;
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
internal class BrowserSkiaRasterSurface : IBrowserSkiaSurface, IFramebufferPlatformSurface, IDisposable
{
diff --git a/src/Web/Avalonia.Web/Skia/BrowserSkiaSurface.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaSurface.cs
similarity index 91%
rename from src/Web/Avalonia.Web/Skia/BrowserSkiaSurface.cs
rename to src/Browser/Avalonia.Browser/Skia/BrowserSkiaSurface.cs
index 27a206c0ec..418b34a975 100644
--- a/src/Web/Avalonia.Web/Skia/BrowserSkiaSurface.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaSurface.cs
@@ -1,7 +1,7 @@
-using Avalonia.Web.Interop;
+using Avalonia.Browser.Interop;
using SkiaSharp;
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
internal class BrowserSkiaSurface : IBrowserSkiaSurface
{
diff --git a/src/Web/Avalonia.Web/Skia/IBrowserSkiaSurface.cs b/src/Browser/Avalonia.Browser/Skia/IBrowserSkiaSurface.cs
similarity index 82%
rename from src/Web/Avalonia.Web/Skia/IBrowserSkiaSurface.cs
rename to src/Browser/Avalonia.Browser/Skia/IBrowserSkiaSurface.cs
index 7301ae45cd..1585d7f283 100644
--- a/src/Web/Avalonia.Web/Skia/IBrowserSkiaSurface.cs
+++ b/src/Browser/Avalonia.Browser/Skia/IBrowserSkiaSurface.cs
@@ -1,4 +1,4 @@
-namespace Avalonia.Web.Skia
+namespace Avalonia.Browser.Skia
{
internal interface IBrowserSkiaSurface
{
diff --git a/src/Web/Avalonia.Web/Storage/BlobReadableStream.cs b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
similarity index 97%
rename from src/Web/Avalonia.Web/Storage/BlobReadableStream.cs
rename to src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
index 640c2fd745..4fce190346 100644
--- a/src/Web/Avalonia.Web/Storage/BlobReadableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
@@ -3,8 +3,9 @@ using System.IO;
using System.Runtime.InteropServices.JavaScript;
using System.Threading;
using System.Threading.Tasks;
+using Avalonia.Browser.Interop;
-namespace Avalonia.Web.Storage;
+namespace Avalonia.Browser.Storage;
[System.Runtime.Versioning.SupportedOSPlatform("browser")]
internal class BlobReadableStream : Stream
diff --git a/src/Web/Avalonia.Web/Storage/BrowserStorageProvider.cs b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
similarity index 95%
rename from src/Web/Avalonia.Web/Storage/BrowserStorageProvider.cs
rename to src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
index 55ae2bdef0..28de55092b 100644
--- a/src/Web/Avalonia.Web/Storage/BrowserStorageProvider.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
@@ -6,11 +6,10 @@ using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
using System.Threading.Tasks;
-
+using Avalonia.Browser.Interop;
using Avalonia.Platform.Storage;
-using Avalonia.Web.Interop;
-namespace Avalonia.Web.Storage;
+namespace Avalonia.Browser.Storage;
internal record FilePickerAcceptType(string Description, IReadOnlyDictionary> Accept);
@@ -20,7 +19,7 @@ internal class BrowserStorageProvider : IStorageProvider
internal const string PickerCancelMessage = "The user aborted a request";
internal const string NoPermissionsMessage = "Permissions denied";
- private readonly Lazy> _lazyModule = new(() => JSHost.ImportAsync("storage.ts", "./storage.js"));
+ private readonly Lazy _lazyModule = new(() => AvaloniaModule.ImportStorage());
public bool CanOpen => StorageHelper.CanShowOpenFilePicker();
public bool CanSave => StorageHelper.CanShowSaveFilePicker();
@@ -28,7 +27,7 @@ internal class BrowserStorageProvider : IStorageProvider
public async Task> OpenFilePickerAsync(FilePickerOpenOptions options)
{
- _ = await _lazyModule.Value;
+ await _lazyModule.Value;
var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
var (types, exludeAll) = ConvertFileTypes(options.FileTypeFilter);
@@ -62,7 +61,7 @@ internal class BrowserStorageProvider : IStorageProvider
public async Task SaveFilePickerAsync(FilePickerSaveOptions options)
{
- _ = await _lazyModule.Value;
+ await _lazyModule.Value;
var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
var (types, exludeAll) = ConvertFileTypes(options.FileTypeChoices);
@@ -90,7 +89,7 @@ internal class BrowserStorageProvider : IStorageProvider
public async Task> OpenFolderPickerAsync(FolderPickerOpenOptions options)
{
- _ = await _lazyModule.Value;
+ await _lazyModule.Value;
var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
try
@@ -106,14 +105,14 @@ internal class BrowserStorageProvider : IStorageProvider
public async Task OpenFileBookmarkAsync(string bookmark)
{
- _ = await _lazyModule.Value;
+ await _lazyModule.Value;
var item = await StorageHelper.OpenBookmark(bookmark);
return item is not null ? new JSStorageFile(item) : null;
}
public async Task OpenFolderBookmarkAsync(string bookmark)
{
- _ = await _lazyModule.Value;
+ await _lazyModule.Value;
var item = await StorageHelper.OpenBookmark(bookmark);
return item is not null ? new JSStorageFolder(item) : null;
}
diff --git a/src/Web/Avalonia.Web/Storage/WriteableStream.cs b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
similarity index 97%
rename from src/Web/Avalonia.Web/Storage/WriteableStream.cs
rename to src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
index f9699fef7a..f29f7420ac 100644
--- a/src/Web/Avalonia.Web/Storage/WriteableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
@@ -3,8 +3,9 @@ using System.IO;
using System.Runtime.InteropServices.JavaScript;
using System.Threading;
using System.Threading.Tasks;
+using Avalonia.Browser.Interop;
-namespace Avalonia.Web.Storage;
+namespace Avalonia.Browser.Storage;
[System.Runtime.Versioning.SupportedOSPlatform("browser")]
// Loose wrapper implementaion of a stream on top of FileAPI FileSystemWritableFileStream
diff --git a/src/Web/Avalonia.Web/WebEmbeddableControlRoot.cs b/src/Browser/Avalonia.Browser/WebEmbeddableControlRoot.cs
similarity index 98%
rename from src/Web/Avalonia.Web/WebEmbeddableControlRoot.cs
rename to src/Browser/Avalonia.Browser/WebEmbeddableControlRoot.cs
index 19f36403ad..e389ee98ea 100644
--- a/src/Web/Avalonia.Web/WebEmbeddableControlRoot.cs
+++ b/src/Browser/Avalonia.Browser/WebEmbeddableControlRoot.cs
@@ -4,7 +4,7 @@ using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
internal class WebEmbeddableControlRoot : EmbeddableControlRoot
{
diff --git a/src/Web/Avalonia.Web/WinStubs.cs b/src/Browser/Avalonia.Browser/WinStubs.cs
similarity index 97%
rename from src/Web/Avalonia.Web/WinStubs.cs
rename to src/Browser/Avalonia.Browser/WinStubs.cs
index b0961115fe..dee97a3612 100644
--- a/src/Web/Avalonia.Web/WinStubs.cs
+++ b/src/Browser/Avalonia.Browser/WinStubs.cs
@@ -4,7 +4,7 @@ using Avalonia.Platform;
#nullable enable
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
internal class IconLoaderStub : IPlatformIconLoader
{
diff --git a/src/Web/Avalonia.Web/WindowingPlatform.cs b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
similarity index 85%
rename from src/Web/Avalonia.Web/WindowingPlatform.cs
rename to src/Browser/Avalonia.Browser/WindowingPlatform.cs
index 3f14680241..6535e9534c 100644
--- a/src/Web/Avalonia.Web/WindowingPlatform.cs
+++ b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
@@ -6,9 +6,9 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
-namespace Avalonia.Web
+namespace Avalonia.Browser
{
- public class BrowserWindowingPlatform : IWindowingPlatform, IPlatformSettings, IPlatformThreadingInterface
+ internal class BrowserWindowingPlatform : IWindowingPlatform, IPlatformThreadingInterface
{
private bool _signaled;
private static KeyboardDevice? s_keyboard;
@@ -31,12 +31,14 @@ namespace Avalonia.Web
public static void Register()
{
var instance = new BrowserWindowingPlatform();
+
s_keyboard = new KeyboardDevice();
AvaloniaLocator.CurrentMutable
+ .Bind().ToSingleton()
.Bind().ToSingleton()
.Bind().ToSingleton()
.Bind().ToConstant(s_keyboard)
- .Bind().ToConstant(instance)
+ .Bind().ToSingleton()
.Bind().ToConstant(instance)
.Bind().ToConstant(new RenderLoop())
.Bind().ToConstant(ManualTriggerRenderTimer.Instance)
@@ -45,13 +47,6 @@ namespace Avalonia.Web
.Bind().ToSingleton();
}
- public Size DoubleClickSize { get; } = new Size(2, 2);
-
- public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
- public Size TouchDoubleClickSize => new Size(16, 16);
-
- public TimeSpan TouchDoubleClickTime => DoubleClickTime;
public void RunLoop(CancellationToken cancellationToken)
{
throw new NotSupportedException();
@@ -71,11 +66,11 @@ namespace Avalonia.Web
{
if (_signaled)
return;
-
+
_signaled = true;
-
+
IDisposable? disp = null;
-
+
disp = GetRuntimePlatform()
.StartSystemTimer(TimeSpan.FromMilliseconds(1),
() =>
diff --git a/src/Web/Avalonia.Web/interop.js b/src/Browser/Avalonia.Browser/interop.js
similarity index 100%
rename from src/Web/Avalonia.Web/interop.js
rename to src/Browser/Avalonia.Browser/interop.js
diff --git a/src/Web/Avalonia.Web/webapp/.eslintrc.json b/src/Browser/Avalonia.Browser/webapp/.eslintrc.json
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/.eslintrc.json
rename to src/Browser/Avalonia.Browser/webapp/.eslintrc.json
diff --git a/src/Web/Avalonia.Web/webapp/build.js b/src/Browser/Avalonia.Browser/webapp/build.js
similarity index 94%
rename from src/Web/Avalonia.Web/webapp/build.js
rename to src/Browser/Avalonia.Browser/webapp/build.js
index 6b6df4c300..81f863cac7 100644
--- a/src/Web/Avalonia.Web/webapp/build.js
+++ b/src/Browser/Avalonia.Browser/webapp/build.js
@@ -5,7 +5,7 @@ require("esbuild").build({
],
outdir: "../wwwroot",
bundle: true,
- minify: false,
+ minify: true,
format: "esm",
target: "es2016",
platform: "browser",
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia.ts
similarity index 65%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia.ts
index 98c912f940..0642bd475d 100644
--- a/src/Web/Avalonia.Web/webapp/modules/avalonia.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia.ts
@@ -6,8 +6,8 @@ import { Caniuse } from "./avalonia/caniuse";
import { StreamHelper } from "./avalonia/stream";
import { NativeControlHost } from "./avalonia/nativeControlHost";
-export async function createAvaloniaRuntime(api: RuntimeAPI): Promise {
- api.setModuleImports("avalonia.ts", {
+async function registerAvaloniaModule(api: RuntimeAPI): Promise {
+ api.setModuleImports("avalonia", {
Caniuse,
Canvas,
InputHelper,
@@ -18,3 +18,15 @@ export async function createAvaloniaRuntime(api: RuntimeAPI): Promise {
NativeControlHost
});
}
+export {
+ Caniuse,
+ Canvas,
+ InputHelper,
+ SizeWatcher,
+ DpiWatcher,
+ AvaloniaDOM,
+ StreamHelper,
+ NativeControlHost,
+
+ registerAvaloniaModule
+};
diff --git a/src/Browser/Avalonia.Browser/webapp/modules/avalonia/caniuse.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/caniuse.ts
new file mode 100644
index 0000000000..e019f92113
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/caniuse.ts
@@ -0,0 +1,25 @@
+export class Caniuse {
+ public static canShowOpenFilePicker(): boolean {
+ return typeof globalThis.showOpenFilePicker !== "undefined";
+ }
+
+ public static canShowSaveFilePicker(): boolean {
+ return typeof globalThis.showSaveFilePicker !== "undefined";
+ }
+
+ public static canShowDirectoryPicker(): boolean {
+ return typeof globalThis.showDirectoryPicker !== "undefined";
+ }
+
+ public static isMobile(): boolean {
+ const userAgentData = (globalThis.navigator as any)?.userAgentData;
+ if (userAgentData) {
+ return userAgentData.mobile;
+ }
+
+ const userAgent = navigator.userAgent;
+ const regex1 = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i;
+ const regex2 = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw(n|u)|c55\/|capi|ccwa|cdm|cell|chtm|cldc|cmd|co(mp|nd)|craw|da(it|ll|ng)|dbte|dcs|devi|dica|dmob|do(c|p)o|ds(12|d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(|_)|g1 u|g560|gene|gf5|gmo|go(\.w|od)|gr(ad|un)|haie|hcit|hd(m|p|t)|hei|hi(pt|ta)|hp( i|ip)|hsc|ht(c(| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i(20|go|ma)|i230|iac( ||\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|[a-w])|libw|lynx|m1w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|mcr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|([1-8]|c))|phil|pire|pl(ay|uc)|pn2|po(ck|rt|se)|prox|psio|ptg|qaa|qc(07|12|21|32|60|[2-7]|i)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h|oo|p)|sdk\/|se(c(|0|1)|47|mc|nd|ri)|sgh|shar|sie(|m)|sk0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h|v|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl|tdg|tel(i|m)|tim|tmo|to(pl|sh)|ts(70|m|m3|m5)|tx9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas|your|zeto|zte/i;
+ return regex1.test(userAgent) || regex2.test(userAgent.substr(0, 4));
+ }
+}
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/canvas.ts
similarity index 92%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/canvas.ts
index 017ca58b8f..47c501cbb7 100644
--- a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/canvas.ts
@@ -106,12 +106,6 @@ export class Canvas {
// add the draw to the next frame
this.renderLoopRequest = window.requestAnimationFrame(() => {
- if (this.glInfo) {
- const GL = (globalThis as any).AvaloniaGL;
- // make current
- GL.makeContextCurrent(this.glInfo.context);
- }
-
if (this.htmlCanvas.width !== this.newWidth) {
this.htmlCanvas.width = this.newWidth ?? 0;
}
@@ -131,6 +125,11 @@ export class Canvas {
}
public setCanvasSize(width: number, height: number): void {
+ if (this.renderLoopRequest !== 0) {
+ window.cancelAnimationFrame(this.renderLoopRequest);
+ this.renderLoopRequest = 0;
+ }
+
this.newWidth = width;
this.newHeight = height;
@@ -142,11 +141,7 @@ export class Canvas {
this.htmlCanvas.height = this.newHeight;
}
- if (this.glInfo) {
- const GL = (globalThis as any).AvaloniaGL;
- // make current
- GL.makeContextCurrent(this.glInfo.context);
- }
+ this.requestAnimationFrame();
}
public static setCanvasSize(element: HTMLCanvasElement, width: number, height: number): void {
@@ -210,23 +205,25 @@ interface SizeWatcherInstance {
export class SizeWatcher {
static observer: ResizeObserver;
static elements: Map;
+ private static lastMove: number;
- public static observe(element: HTMLElement, elementId: string, callback: (width: number, height: number) => void): void {
+ public static observe(element: HTMLElement, elementId: string | undefined, callback: (width: number, height: number) => void): void {
if (!element || !callback) {
return;
}
- SizeWatcher.init();
+ SizeWatcher.lastMove = Date.now();
- const watcherElement = element as SizeWatcherElement;
- watcherElement.SizeWatcher = {
- callback
- };
+ callback(element.clientWidth, element.clientHeight);
- SizeWatcher.elements.set(elementId, element);
- SizeWatcher.observer.observe(element);
+ const handleResize = (args: UIEvent) => {
+ if (Date.now() - SizeWatcher.lastMove > 33) {
+ callback(element.clientWidth, element.clientHeight);
+ SizeWatcher.lastMove = Date.now();
+ }
+ };
- SizeWatcher.invoke(element);
+ window.addEventListener("resize", handleResize);
}
public static unobserve(elementId: string): void {
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/caretHelper.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/caretHelper.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/caretHelper.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/caretHelper.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
similarity index 85%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
index 943b8330d5..385cdd4c41 100644
--- a/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
@@ -4,21 +4,26 @@ export class AvaloniaDOM {
}
static createAvaloniaHost(host: HTMLElement) {
+ const randomIdPart = Math.random().toString(36).replace(/[^a-z]+/g, "").substr(2, 10);
+
// Root element
host.classList.add("avalonia-container");
host.tabIndex = 0;
host.oncontextmenu = function () { return false; };
+ host.style.overflow = "hidden";
+ host.style.touchAction = "none";
// Rendering target canvas
const canvas = document.createElement("canvas");
+ canvas.id = `canvas${randomIdPart}`;
canvas.classList.add("avalonia-canvas");
canvas.style.backgroundColor = "#ccc";
canvas.style.width = "100%";
- canvas.style.height = "100%";
canvas.style.position = "absolute";
// Native controls host
const nativeHost = document.createElement("div");
+ nativeHost.id = `nativeHost${randomIdPart}`;
nativeHost.classList.add("avalonia-native-host");
nativeHost.style.left = "0px";
nativeHost.style.top = "0px";
@@ -28,6 +33,7 @@ export class AvaloniaDOM {
// IME
const inputElement = document.createElement("input");
+ inputElement.id = `inputElement${randomIdPart}`;
inputElement.classList.add("avalonia-input-element");
inputElement.autocapitalize = "none";
inputElement.type = "text";
@@ -42,6 +48,7 @@ export class AvaloniaDOM {
inputElement.style.color = "transparent";
inputElement.style.display = "none";
inputElement.style.height = "20px";
+ inputElement.style.zIndex = "-1";
inputElement.onpaste = function () { return false; };
inputElement.oncopy = function () { return false; };
inputElement.oncut = function () { return false; };
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/input.ts
similarity index 87%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/input.ts
index 768414ccab..83e8ee7f1c 100644
--- a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/input.ts
@@ -95,41 +95,45 @@ export class InputHelper {
pointerMoveCallback: (args: PointerEvent) => boolean,
pointerDownCallback: (args: PointerEvent) => boolean,
pointerUpCallback: (args: PointerEvent) => boolean,
+ pointerCancelCallback: (args: PointerEvent) => boolean,
wheelCallback: (args: WheelEvent) => boolean
) {
const pointerMoveHandler = (args: PointerEvent) => {
- if (pointerMoveCallback(args)) {
- args.preventDefault();
- }
+ pointerMoveCallback(args);
+ args.preventDefault();
};
const pointerDownHandler = (args: PointerEvent) => {
- if (pointerDownCallback(args)) {
- args.preventDefault();
- }
+ pointerDownCallback(args);
+ args.preventDefault();
};
const pointerUpHandler = (args: PointerEvent) => {
- if (pointerUpCallback(args)) {
- args.preventDefault();
- }
+ pointerUpCallback(args);
+ args.preventDefault();
+ };
+
+ const pointerCancelHandler = (args: PointerEvent) => {
+ pointerCancelCallback(args);
+ args.preventDefault();
};
const wheelHandler = (args: WheelEvent) => {
- if (wheelCallback(args)) {
- args.preventDefault();
- }
+ wheelCallback(args);
+ args.preventDefault();
};
element.addEventListener("pointermove", pointerMoveHandler);
element.addEventListener("pointerdown", pointerDownHandler);
element.addEventListener("pointerup", pointerUpHandler);
element.addEventListener("wheel", wheelHandler);
+ element.addEventListener("pointercancel", pointerCancelHandler);
return () => {
element.removeEventListener("pointerover", pointerMoveHandler);
element.removeEventListener("pointerdown", pointerDownHandler);
element.removeEventListener("pointerup", pointerUpHandler);
+ element.removeEventListener("pointercancel", pointerCancelHandler);
element.removeEventListener("wheel", wheelHandler);
};
}
@@ -150,6 +154,10 @@ export class InputHelper {
};
}
+ public static getCoalescedEvents(pointerEvent: PointerEvent): PointerEvent[] {
+ return pointerEvent.getCoalescedEvents();
+ }
+
public static clearInput(inputElement: HTMLInputElement) {
inputElement.value = "";
}
@@ -159,7 +167,11 @@ export class InputHelper {
}
public static setCursor(inputElement: HTMLInputElement, kind: string) {
- inputElement.style.cursor = kind;
+ if (kind === "pointer") {
+ inputElement.style.removeProperty("cursor");
+ } else {
+ inputElement.style.cursor = kind;
+ }
}
public static setBounds(inputElement: HTMLInputElement, x: number, y: number, caretWidth: number, caretHeight: number, caret: number) {
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/nativeControlHost.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/nativeControlHost.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/nativeControlHost.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/nativeControlHost.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/stream.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/stream.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/avalonia/stream.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/avalonia/stream.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/storage.ts b/src/Browser/Avalonia.Browser/webapp/modules/storage.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/storage.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/storage.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/storage/indexedDb.ts b/src/Browser/Avalonia.Browser/webapp/modules/storage/indexedDb.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/storage/indexedDb.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/storage/indexedDb.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/storage/storageItem.ts b/src/Browser/Avalonia.Browser/webapp/modules/storage/storageItem.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/storage/storageItem.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/storage/storageItem.ts
diff --git a/src/Web/Avalonia.Web/webapp/modules/storage/storageProvider.ts b/src/Browser/Avalonia.Browser/webapp/modules/storage/storageProvider.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/modules/storage/storageProvider.ts
rename to src/Browser/Avalonia.Browser/webapp/modules/storage/storageProvider.ts
diff --git a/src/Browser/Avalonia.Browser/webapp/package-lock.json b/src/Browser/Avalonia.Browser/webapp/package-lock.json
new file mode 100644
index 0000000000..06e94629d7
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/webapp/package-lock.json
@@ -0,0 +1,5496 @@
+{
+ "name": "avalonia.browser",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "avalonia.browser",
+ "devDependencies": {
+ "@types/emscripten": "^1.39.6",
+ "@types/wicg-file-system-access": "^2020.9.5",
+ "@typescript-eslint/eslint-plugin": "^5.38.1",
+ "esbuild": "^0.15.7",
+ "eslint": "^8.24.0",
+ "eslint-config-standard-with-typescript": "^23.0.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-n": "^15.3.0",
+ "eslint-plugin-promise": "^6.0.1",
+ "npm-run-all": "^4.1.5",
+ "typescript": "^4.8.3"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.9.tgz",
+ "integrity": "sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz",
+ "integrity": "sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz",
+ "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
+ "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@types/emscripten": {
+ "version": "1.39.6",
+ "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
+ "integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/wicg-file-system-access": {
+ "version": "2020.9.5",
+ "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.5.tgz",
+ "integrity": "sha512-UYK244awtmcUYQfs7FR8710MJcefL2WvkyHMjA8yJzxd1mo0Gfn88sRZ1Bls7hiUhA2w7ne1gpJ9T5g3G0wOyA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz",
+ "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/type-utils": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "ignore": "^5.2.0",
+ "regexpp": "^3.2.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz",
+ "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz",
+ "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz",
+ "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz",
+ "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz",
+ "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz",
+ "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz",
+ "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.38.1",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
+ "get-intrinsic": "^1.1.1",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz",
+ "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.0.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz",
+ "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.3",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.6",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.2",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.9.tgz",
+ "integrity": "sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.9",
+ "@esbuild/linux-loong64": "0.15.9",
+ "esbuild-android-64": "0.15.9",
+ "esbuild-android-arm64": "0.15.9",
+ "esbuild-darwin-64": "0.15.9",
+ "esbuild-darwin-arm64": "0.15.9",
+ "esbuild-freebsd-64": "0.15.9",
+ "esbuild-freebsd-arm64": "0.15.9",
+ "esbuild-linux-32": "0.15.9",
+ "esbuild-linux-64": "0.15.9",
+ "esbuild-linux-arm": "0.15.9",
+ "esbuild-linux-arm64": "0.15.9",
+ "esbuild-linux-mips64le": "0.15.9",
+ "esbuild-linux-ppc64le": "0.15.9",
+ "esbuild-linux-riscv64": "0.15.9",
+ "esbuild-linux-s390x": "0.15.9",
+ "esbuild-netbsd-64": "0.15.9",
+ "esbuild-openbsd-64": "0.15.9",
+ "esbuild-sunos-64": "0.15.9",
+ "esbuild-windows-32": "0.15.9",
+ "esbuild-windows-64": "0.15.9",
+ "esbuild-windows-arm64": "0.15.9"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz",
+ "integrity": "sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz",
+ "integrity": "sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz",
+ "integrity": "sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz",
+ "integrity": "sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz",
+ "integrity": "sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz",
+ "integrity": "sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz",
+ "integrity": "sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz",
+ "integrity": "sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz",
+ "integrity": "sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz",
+ "integrity": "sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz",
+ "integrity": "sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz",
+ "integrity": "sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz",
+ "integrity": "sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz",
+ "integrity": "sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz",
+ "integrity": "sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz",
+ "integrity": "sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz",
+ "integrity": "sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz",
+ "integrity": "sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz",
+ "integrity": "sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz",
+ "integrity": "sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.24.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
+ "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/eslintrc": "^1.3.2",
+ "@humanwhocodes/config-array": "^0.10.5",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.4.0",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-sdsl": "^4.1.4",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-standard": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
+ "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "peerDependencies": {
+ "eslint": "^8.0.1",
+ "eslint-plugin-import": "^2.25.2",
+ "eslint-plugin-n": "^15.0.0",
+ "eslint-plugin-promise": "^6.0.0"
+ }
+ },
+ "node_modules/eslint-config-standard-with-typescript": {
+ "version": "23.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-23.0.0.tgz",
+ "integrity": "sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint-config-standard": "17.0.0"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
+ "eslint": "^8.0.1",
+ "eslint-plugin-import": "^2.25.2",
+ "eslint-plugin-n": "^15.0.0",
+ "eslint-plugin-promise": "^6.0.0",
+ "typescript": "*"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
+ "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "resolve": "^1.20.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
+ "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-es": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz",
+ "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==",
+ "dev": true,
+ "dependencies": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=4.19.1"
+ }
+ },
+ "node_modules/eslint-plugin-es/node_modules/eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.26.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
+ "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.4",
+ "array.prototype.flat": "^1.2.5",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-module-utils": "^2.7.3",
+ "has": "^1.0.3",
+ "is-core-module": "^2.8.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.5",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-n": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.3.0.tgz",
+ "integrity": "sha512-IyzPnEWHypCWasDpxeJnim60jhlumbmq0pubL6IOcnk8u2y53s5QfT8JnXy7skjHJ44yWHRb11PLtDHuu1kg/Q==",
+ "dev": true,
+ "dependencies": {
+ "builtins": "^5.0.1",
+ "eslint-plugin-es": "^4.1.0",
+ "eslint-utils": "^3.0.0",
+ "ignore": "^5.1.1",
+ "is-core-module": "^2.10.0",
+ "minimatch": "^3.1.2",
+ "resolve": "^1.22.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-promise": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz",
+ "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-sdsl": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
+ "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "bin": {
+ "npm-run-all": "bin/npm-run-all/index.js",
+ "run-p": "bin/run-p/index.js",
+ "run-s": "bin/run-s/index.js"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/npm-run-all/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
+ "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true,
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "dependencies": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg/node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
+ "dev": true
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz",
+ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==",
+ "dev": true
+ },
+ "node_modules/string.prototype.padend": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz",
+ "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
+ "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.1",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+ "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@esbuild/android-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.9.tgz",
+ "integrity": "sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz",
+ "integrity": "sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==",
+ "dev": true,
+ "optional": true
+ },
+ "@eslint/eslintrc": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz",
+ "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
+ "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@types/emscripten": {
+ "version": "1.39.6",
+ "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
+ "integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==",
+ "dev": true
+ },
+ "@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "@types/wicg-file-system-access": {
+ "version": "2020.9.5",
+ "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.5.tgz",
+ "integrity": "sha512-UYK244awtmcUYQfs7FR8710MJcefL2WvkyHMjA8yJzxd1mo0Gfn88sRZ1Bls7hiUhA2w7ne1gpJ9T5g3G0wOyA==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz",
+ "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/type-utils": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "ignore": "^5.2.0",
+ "regexpp": "^3.2.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz",
+ "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "debug": "^4.3.4"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz",
+ "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz",
+ "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz",
+ "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz",
+ "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz",
+ "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.9",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz",
+ "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.38.1",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "acorn": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "array-includes": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
+ "get-intrinsic": "^1.1.1",
+ "is-string": "^1.0.7"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "array.prototype.flat": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz",
+ "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.2",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.0.0"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "requires": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz",
+ "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.3",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.6",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.2",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ }
+ },
+ "es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "esbuild": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.9.tgz",
+ "integrity": "sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.15.9",
+ "@esbuild/linux-loong64": "0.15.9",
+ "esbuild-android-64": "0.15.9",
+ "esbuild-android-arm64": "0.15.9",
+ "esbuild-darwin-64": "0.15.9",
+ "esbuild-darwin-arm64": "0.15.9",
+ "esbuild-freebsd-64": "0.15.9",
+ "esbuild-freebsd-arm64": "0.15.9",
+ "esbuild-linux-32": "0.15.9",
+ "esbuild-linux-64": "0.15.9",
+ "esbuild-linux-arm": "0.15.9",
+ "esbuild-linux-arm64": "0.15.9",
+ "esbuild-linux-mips64le": "0.15.9",
+ "esbuild-linux-ppc64le": "0.15.9",
+ "esbuild-linux-riscv64": "0.15.9",
+ "esbuild-linux-s390x": "0.15.9",
+ "esbuild-netbsd-64": "0.15.9",
+ "esbuild-openbsd-64": "0.15.9",
+ "esbuild-sunos-64": "0.15.9",
+ "esbuild-windows-32": "0.15.9",
+ "esbuild-windows-64": "0.15.9",
+ "esbuild-windows-arm64": "0.15.9"
+ }
+ },
+ "esbuild-android-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz",
+ "integrity": "sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-android-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz",
+ "integrity": "sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz",
+ "integrity": "sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz",
+ "integrity": "sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz",
+ "integrity": "sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz",
+ "integrity": "sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz",
+ "integrity": "sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz",
+ "integrity": "sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz",
+ "integrity": "sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz",
+ "integrity": "sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-mips64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz",
+ "integrity": "sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-ppc64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz",
+ "integrity": "sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-riscv64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz",
+ "integrity": "sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-s390x": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz",
+ "integrity": "sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-netbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz",
+ "integrity": "sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-openbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz",
+ "integrity": "sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-sunos-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz",
+ "integrity": "sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz",
+ "integrity": "sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz",
+ "integrity": "sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz",
+ "integrity": "sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==",
+ "dev": true,
+ "optional": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "eslint": {
+ "version": "8.24.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
+ "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
+ "dev": true,
+ "requires": {
+ "@eslint/eslintrc": "^1.3.2",
+ "@humanwhocodes/config-array": "^0.10.5",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.4.0",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-sdsl": "^4.1.4",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ }
+ }
+ },
+ "eslint-config-standard": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
+ "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-config-standard-with-typescript": {
+ "version": "23.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-23.0.0.tgz",
+ "integrity": "sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint-config-standard": "17.0.0"
+ }
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
+ "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7",
+ "resolve": "^1.20.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
+ "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "eslint-plugin-es": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz",
+ "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==",
+ "dev": true,
+ "requires": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ },
+ "dependencies": {
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.26.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
+ "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.4",
+ "array.prototype.flat": "^1.2.5",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-module-utils": "^2.7.3",
+ "has": "^1.0.3",
+ "is-core-module": "^2.8.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.5",
+ "resolve": "^1.22.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-n": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.3.0.tgz",
+ "integrity": "sha512-IyzPnEWHypCWasDpxeJnim60jhlumbmq0pubL6IOcnk8u2y53s5QfT8JnXy7skjHJ44yWHRb11PLtDHuu1kg/Q==",
+ "dev": true,
+ "requires": {
+ "builtins": "^5.0.1",
+ "eslint-plugin-es": "^4.1.0",
+ "eslint-utils": "^3.0.0",
+ "ignore": "^5.1.1",
+ "is-core-module": "^2.10.0",
+ "minimatch": "^3.1.2",
+ "resolve": "^1.22.1",
+ "semver": "^7.3.7"
+ }
+ },
+ "eslint-plugin-promise": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz",
+ "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true
+ },
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "js-sdsl": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
+ "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
+ "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ }
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "shell-quote": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
+ "dev": true
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz",
+ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==",
+ "dev": true
+ },
+ "string.prototype.padend": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz",
+ "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tsconfig-paths": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
+ "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "dev": true,
+ "requires": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.1",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+ "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
+ "dev": true
+ },
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/src/Web/Avalonia.Web/webapp/package.json b/src/Browser/Avalonia.Browser/webapp/package.json
similarity index 95%
rename from src/Web/Avalonia.Web/webapp/package.json
rename to src/Browser/Avalonia.Browser/webapp/package.json
index 8845dec604..05a3976ccc 100644
--- a/src/Web/Avalonia.Web/webapp/package.json
+++ b/src/Browser/Avalonia.Browser/webapp/package.json
@@ -1,5 +1,5 @@
{
- "name": "avalonia.web",
+ "name": "avalonia.browser",
"scripts": {
"typecheck": "npx tsc -noEmit",
"eslint": "npx eslint . --fix",
diff --git a/src/Web/Avalonia.Web/webapp/tsconfig.json b/src/Browser/Avalonia.Browser/webapp/tsconfig.json
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/tsconfig.json
rename to src/Browser/Avalonia.Browser/webapp/tsconfig.json
diff --git a/src/Web/Avalonia.Web/webapp/types/dotnet.d.ts b/src/Browser/Avalonia.Browser/webapp/types/dotnet.d.ts
similarity index 100%
rename from src/Web/Avalonia.Web/webapp/types/dotnet.d.ts
rename to src/Browser/Avalonia.Browser/webapp/types/dotnet.d.ts
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 869602e452..55a1014188 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -2,6 +2,7 @@
+
Shared\_ModuleInitializer.cs
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
index e92ad02c7a..ce843952e7 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
@@ -23,5 +23,11 @@ namespace Avalonia.LinuxFramebuffer
/// Default: R0 G0 B0 A0
///
public Color InitialBufferSwappingColor { get; set; } = new Color(0, 0, 0, 0);
+
+ ///
+ /// specific the video mode with which the DrmOutput should be created, if it is not found it will fallback to the preferred mode.
+ /// If NULL preferred mode will be used.
+ ///
+ public PixelSize? VideoMode { get; set; }
}
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
new file mode 100644
index 0000000000..ef039a38bc
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
@@ -0,0 +1,110 @@
+using System;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Logging;
+using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
+
+namespace Avalonia.LinuxFramebuffer.Input.LibInput;
+
+public partial class LibInputBackend
+{
+ private MouseDevice _mouse = new MouseDevice();
+ private Point _mousePosition;
+ private const string Pointer = LibInput + "/" + nameof(Pointer);
+
+ private void HandlePointer(IntPtr ev, LibInputEventType type)
+ {
+ var modifiers = RawInputModifiers.None; //TODO: support input modifiers
+ var pev = libinput_event_get_pointer_event(ev);
+ var info = _screen.ScaledSize;
+ var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
+ switch (type)
+ {
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+ _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
+ libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
+ ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
+ modifiers));
+ break;
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON:
+ {
+ var button = (EvKey)libinput_event_pointer_get_button(pev);
+ var buttonState = libinput_event_pointer_get_button_state(pev);
+
+ RawPointerEventArgs evnt = button switch
+ {
+ EvKey.BTN_LEFT when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_LEFT when buttonState == 0
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers),
+ EvKey.BTN_RIGHT when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers),
+ EvKey.BTN_RIGHT when buttonState == 2
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_MIDDLE when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_MIDDLE when buttonState == 2
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers),
+ _ => default,
+ };
+ if (evnt is not null)
+ {
+ ScheduleInput(evnt);
+ }
+ else
+ {
+ Logger.TryGet(LogEventLevel.Warning, Pointer)
+ ?.Log(this, $"The button {button} is not associated");
+ }
+ }
+ break;
+ // Backward compatibility with low-res wheel
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_AXIS:
+ {
+ var sourceAxis = libinput_event_pointer_get_axis_source(pev);
+ switch (sourceAxis)
+ {
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
+ {
+ var value = libinput_event_pointer_get_axis_value_discrete(pev,
+ LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
+ ScheduleInput(new RawMouseWheelEventArgs(_mouse
+ , ts
+ , _inputRoot
+ , _mousePosition
+ , new Vector(0, -value)
+ , modifiers));
+ }
+ break;
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
+ default:
+ Logger.TryGet(LogEventLevel.Debug, Pointer)
+ ?.Log(this, $"The pointer axis {sourceAxis} is not managed.");
+ break;
+ }
+ }
+ break;
+ // Hi-Res wheel
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
+ {
+ var value = new Vector(0,
+ -libinput_event_pointer_get_scroll_value_v120(pev,
+ LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / 120);
+ ScheduleInput(new RawMouseWheelEventArgs(_mouse
+ , ts
+ , _inputRoot
+ , _mousePosition
+ , value
+ , modifiers));
+ }
+ break;
+ default:
+ Logger.TryGet(LogEventLevel.Warning, Pointer)
+ ?.Log(this, $"The pointer event {type} is not mapped.");
+ break;
+ }
+
+ }
+}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
index 702ae3f8e5..77e8202fac 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
@@ -4,18 +4,16 @@ using System.IO;
using System.Threading;
using Avalonia.Input;
using Avalonia.Input.Raw;
-using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
+using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
- public class LibInputBackend : IInputBackend
+ public partial class LibInputBackend : IInputBackend
{
private IScreenInfoProvider _screen;
private IInputRoot _inputRoot;
private readonly Queue _inputThreadActions = new Queue();
private TouchDevice _touch = new TouchDevice();
- private MouseDevice _mouse = new MouseDevice();
- private Point _mousePosition;
-
+ private const string LibInput = nameof(Avalonia.LinuxFramebuffer) + "/" + nameof(Avalonia.LinuxFramebuffer.Input) + "/" + nameof(LibInput);
private readonly RawEventGroupingThreadingHelper _inputQueue;
private Action _onInput;
private Dictionary _pointers = new Dictionary();
@@ -24,13 +22,13 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
var ctx = libinput_path_create_context();
_inputQueue = new(e => _onInput?.Invoke(e));
- new Thread(()=>InputThread(ctx)).Start();
+ new Thread(() => InputThread(ctx)).Start();
}
private unsafe void InputThread(IntPtr ctx)
{
var fd = libinput_get_fd(ctx);
-
+
var timeval = stackalloc IntPtr[2];
@@ -38,12 +36,11 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
libinput_path_add_device(ctx, f);
while (true)
{
-
IntPtr ev;
libinput_dispatch(ctx);
while ((ev = libinput_get_event(ctx)) != IntPtr.Zero)
{
-
+
var type = libinput_event_get_type(ev);
if (type >= LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN &&
type <= LibInputEventType.LIBINPUT_EVENT_TOUCH_CANCEL)
@@ -52,12 +49,12 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
if (type >= LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION
&& type <= LibInputEventType.LIBINPUT_EVENT_POINTER_AXIS)
HandlePointer(ev, type);
-
+
libinput_event_destroy(ev);
libinput_dispatch(ctx);
}
- pollfd pfd = new pollfd {fd = fd, events = 1};
+ pollfd pfd = new pollfd { fd = fd, events = 1 };
NativeUnsafeMethods.poll(&pfd, new IntPtr(1), 10);
}
}
@@ -67,7 +64,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
private void HandleTouch(IntPtr ev, LibInputEventType type)
{
var tev = libinput_event_get_touch_event(ev);
- if(tev == IntPtr.Zero)
+ if (tev == IntPtr.Zero)
return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{
@@ -102,44 +99,6 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
}
}
- private void HandlePointer(IntPtr ev, LibInputEventType type)
- {
- //TODO: support input modifiers
- var pev = libinput_event_get_pointer_event(ev);
- var info = _screen.ScaledSize;
- var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
- if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE)
- {
- _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
- libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
- ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
- RawInputModifiers.None));
- }
- else if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON)
- {
- var button = (EvKey)libinput_event_pointer_get_button(pev);
- var buttonState = libinput_event_pointer_get_button_state(pev);
-
-
- var evnt = button == EvKey.BTN_LEFT ?
- (buttonState == 1 ? RawPointerEventType.LeftButtonDown : RawPointerEventType.LeftButtonUp) :
- button == EvKey.BTN_MIDDLE ?
- (buttonState == 1 ? RawPointerEventType.MiddleButtonDown : RawPointerEventType.MiddleButtonUp) :
- button == EvKey.BTN_RIGHT ?
- (buttonState == 1 ?
- RawPointerEventType.RightButtonDown :
- RawPointerEventType.RightButtonUp) :
- (RawPointerEventType)(-1);
- if (evnt == (RawPointerEventType)(-1))
- return;
-
-
- ScheduleInput(
- new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, RawInputModifiers.None));
- }
-
- }
-
public void Initialize(IScreenInfoProvider screen, Action onInput)
{
_screen = screen;
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
index 0492090461..df6defb653 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
@@ -77,6 +77,9 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
LIBINPUT_EVENT_POINTER_BUTTON,
LIBINPUT_EVENT_POINTER_AXIS,
+ LIBINPUT_EVENT_POINTER_SCROLL_WHEEL,
+ LIBINPUT_EVENT_POINTER_SCROLL_FINGER,
+ LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
LIBINPUT_EVENT_TOUCH_DOWN = 500,
LIBINPUT_EVENT_TOUCH_UP,
LIBINPUT_EVENT_TOUCH_MOTION,
@@ -97,8 +100,38 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
LIBINPUT_EVENT_GESTURE_PINCH_END,
LIBINPUT_EVENT_SWITCH_TOGGLE = 900,
}
-
-
+
+ public enum LibInputPointerAxisSource
+ {
+ /**
+ * The event is caused by the rotation of a wheel.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_WHEEL = 1,
+ /**
+ * The event is caused by the movement of one or more fingers on a device.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
+ /**
+ * The event is caused by the motion of some device.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
+ /**
+ * The event is caused by the tilting of a mouse wheel rather than
+ * its rotation. This method is commonly used on mice without
+ * separate horizontal scroll wheels.
+ * @deprecated This axis source is deprecated as of libinput 1.16.
+ * It was never used by any device before libinput 1.16. All wheel
+ * tilt devices use @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL instead.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT,
+ };
+
+ public enum LibInputPointerAxis
+ {
+ LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL = 0,
+ LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL = 1,
+ };
+
[DllImport(LibInput)]
public extern static void libinput_event_destroy(IntPtr ev);
@@ -119,21 +152,29 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
[DllImport(LibInput)]
public extern static IntPtr libinput_event_get_pointer_event(IntPtr ev);
-
-
+
[DllImport(LibInput)]
public extern static ulong libinput_event_pointer_get_time_usec(IntPtr ev);
[DllImport(LibInput)]
public extern static double libinput_event_pointer_get_absolute_x_transformed(IntPtr ev, int width);
-
+
[DllImport(LibInput)]
public extern static double libinput_event_pointer_get_absolute_y_transformed(IntPtr ev, int height);
-
+
[DllImport(LibInput)]
public extern static int libinput_event_pointer_get_button(IntPtr ev);
[DllImport(LibInput)]
public extern static int libinput_event_pointer_get_button_state(IntPtr ev);
+
+ [DllImport(LibInput)]
+ public extern static LibInputPointerAxisSource libinput_event_pointer_get_axis_source(IntPtr ev);
+
+ [DllImport((LibInput))]
+ public extern static double libinput_event_pointer_get_axis_value_discrete(IntPtr ev, LibInputPointerAxis axis);
+
+ [DllImport(LibInput)]
+ public extern static double libinput_event_pointer_get_scroll_value_v120(IntPtr ev, LibInputPointerAxis axis);
}
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
index 730eb0071d..d881a97af2 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
@@ -51,7 +51,7 @@ namespace Avalonia.LinuxFramebuffer
.Bind().ToConstant(new RenderLoop())
.Bind().ToTransient()
.Bind().ToConstant(new KeyboardDevice())
- .Bind().ToSingleton()
+ .Bind().ToSingleton()
.Bind().ToSingleton();
Compositor = new Compositor(
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index ce210019c0..a4d7d8b1eb 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -51,7 +51,16 @@ namespace Avalonia.LinuxFramebuffer.Output
if(connector == null)
throw new InvalidOperationException("Unable to find connected DRM connector");
- var mode = connector.Modes.OrderByDescending(x => x.IsPreferred)
+ DrmModeInfo? mode = null;
+
+ if (options?.VideoMode != null)
+ {
+ mode = connector.Modes
+ .FirstOrDefault(x => x.Resolution.Width == options.VideoMode.Value.Width &&
+ x.Resolution.Height == options.VideoMode.Value.Height);
+ }
+
+ mode ??= connector.Modes.OrderByDescending(x => x.IsPreferred)
.ThenByDescending(x => x.Resolution.Width * x.Resolution.Height)
//.OrderByDescending(x => x.Resolution.Width * x.Resolution.Height)
.FirstOrDefault();
@@ -99,7 +108,7 @@ namespace Avalonia.LinuxFramebuffer.Output
// prepare for the new ioctl call
var handles = new uint[] {handle, 0, 0, 0};
var pitches = new uint[] {stride, 0, 0, 0};
- var offsets = new uint[] {};
+ var offsets = Array.Empty();
var ret = drmModeAddFB2(_card.Fd, w, h, format, handles, pitches,
offsets, out var fbHandle, 0);
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Stubs.cs b/src/Linux/Avalonia.LinuxFramebuffer/Stubs.cs
index dd60d5f09d..c5c7c13c67 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Stubs.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Stubs.cs
@@ -14,13 +14,4 @@ namespace Avalonia.LinuxFramebuffer
public void Dispose() { }
}
}
- internal class PlatformSettings : IPlatformSettings
- {
- public Size DoubleClickSize { get; } = new Size(4, 4);
- public TimeSpan DoubleClickTime { get; } = new TimeSpan(0, 0, 0, 0, 500);
-
- public Size TouchDoubleClickSize => new Size(16,16);
-
- public TimeSpan TouchDoubleClickTime => DoubleClickTime;
- }
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
index ce931b9c14..1dc7ce5e99 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
@@ -6,6 +6,10 @@
Avalonia.Markup.Xaml.Loader
$(DefineConstants);XAMLX_INTERNAL
+
+
+ false
+
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
index 4df07bcdd8..9393bb0aa4 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
@@ -26,6 +26,22 @@ namespace Avalonia.Markup.Xaml
return Load(stream, localAssembly, rootInstance, uri, designMode);
}
}
+
+ ///
+ /// Loads XAML from a string.
+ ///
+ /// The string containing the XAML.
+ /// Xaml loader configuration.
+ /// The loaded object.
+ public static object Load(string xaml, RuntimeXamlLoaderConfiguration configuration)
+ {
+ Contract.Requires(xaml != null);
+
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
+ {
+ return Load(stream, configuration);
+ }
+ }
///
/// Loads XAML from a stream.
@@ -38,7 +54,17 @@ namespace Avalonia.Markup.Xaml
/// The loaded object.
public static object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null,
bool designMode = false)
- => AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, designMode);
+ => AvaloniaXamlIlRuntimeCompiler.Load(stream, localAssembly, rootInstance, uri, designMode, false);
+
+ ///
+ /// Loads XAML from a stream.
+ ///
+ /// The stream containing the XAML.
+ /// Xaml loader configuration.
+ /// The loaded object.
+ public static object Load(Stream stream, RuntimeXamlLoaderConfiguration configuration)
+ => AvaloniaXamlIlRuntimeCompiler.Load(stream, configuration.LocalAssembly, configuration.RootInstance,
+ configuration.BaseUri, configuration.DesignMode, configuration.UseCompiledBindingsByDefault);
///
/// Parse XAML from a string.
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
index 1e2a77c34d..b4b258e53e 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
@@ -150,12 +150,12 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
- static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode)
+ static object LoadSre(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode, bool useCompiledBindingsByDefault)
{
var success = false;
try
{
- var rv = LoadSreCore(xaml, localAssembly, rootInstance, uri, isDesignMode);
+ var rv = LoadSreCore(xaml, localAssembly, rootInstance, uri, isDesignMode, useCompiledBindingsByDefault);
success = true;
return rv;
}
@@ -167,7 +167,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
- static object LoadSreCore(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode)
+ static object LoadSreCore(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool isDesignMode, bool useCompiledBindingsByDefault)
{
InitializeSre();
@@ -178,15 +178,14 @@ namespace Avalonia.Markup.Xaml.XamlIl
var clrPropertyBuilder = tb.DefineNestedType("ClrProperties_" + Guid.NewGuid().ToString("N"));
var indexerClosureType = _sreBuilder.DefineType("IndexerClosure_" + Guid.NewGuid().ToString("N"));
var trampolineBuilder = _sreBuilder.DefineType("Trampolines_" + Guid.NewGuid().ToString("N"));
-
+
var compiler = new AvaloniaXamlIlCompiler(new AvaloniaXamlIlCompilerConfiguration(_sreTypeSystem, asm,
_sreMappings, _sreXmlns, AvaloniaXamlIlLanguage.CustomValueConverter,
new XamlIlClrPropertyInfoEmitter(_sreTypeSystem.CreateTypeBuilder(clrPropertyBuilder)),
new XamlIlPropertyInfoAccessorFactoryEmitter(_sreTypeSystem.CreateTypeBuilder(indexerClosureType)),
new XamlIlTrampolineBuilder(_sreTypeSystem.CreateTypeBuilder(trampolineBuilder))),
_sreEmitMappings,
- _sreContextType) { EnableIlVerification = true };
-
+ _sreContextType) { EnableIlVerification = true, DefaultCompileBindings = useCompiledBindingsByDefault };
IXamlType overrideType = null;
if (rootInstance != null)
@@ -198,13 +197,14 @@ namespace Avalonia.Markup.Xaml.XamlIl
compiler.ParseAndCompile(xaml, uri?.ToString(), null, _sreTypeSystem.CreateTypeBuilder(tb), overrideType);
var created = tb.CreateTypeInfo();
clrPropertyBuilder.CreateTypeInfo();
+ indexerClosureType.CreateTypeInfo();
trampolineBuilder.CreateTypeInfo();
return LoadOrPopulate(created, rootInstance);
}
#endif
-
- static object LoadOrPopulate(Type created, object rootInstance)
+
+ static object LoadOrPopulate(Type created, object rootInstance)
{
var isp = Expression.Parameter(typeof(IServiceProvider));
@@ -250,15 +250,15 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
public static object Load(Stream stream, Assembly localAssembly, object rootInstance, Uri uri,
- bool isDesignMode)
+ bool isDesignMode, bool useCompiledBindingsByDefault)
{
string xaml;
using (var sr = new StreamReader(stream))
xaml = sr.ReadToEnd();
#if RUNTIME_XAML_CECIL
- return LoadCecil(xaml, localAssembly, rootInstance, uri);
+ return LoadCecil(xaml, localAssembly, rootInstance, uri, useCompiledBindingsByDefault);
#else
- return LoadSre(xaml, localAssembly, rootInstance, uri, isDesignMode);
+ return LoadSre(xaml, localAssembly, rootInstance, uri, isDesignMode, useCompiledBindingsByDefault);
#endif
}
@@ -292,7 +292,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
private static Dictionary _cecilGeneratedCache = new Dictionary();
- static object LoadCecil(string xaml, Assembly localAssembly, object rootInstance, Uri uri)
+ static object LoadCecil(string xaml, Assembly localAssembly, object rootInstance, Uri uri, bool useCompiledBindingsByDefault)
{
if (uri == null)
throw new InvalidOperationException("Please, go away");
@@ -302,8 +302,6 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
overrideType = _cecilTypeSystem.GetType(rootInstance.GetType().FullName);
}
-
-
var safeUri = uri.ToString()
.Replace(":", "_")
@@ -327,13 +325,16 @@ namespace Avalonia.Markup.Xaml.XamlIl
asm.MainModule.Types.Add(contextDef);
var tb = _cecilTypeSystem.CreateTypeBuilder(def);
-
+
var compiler = new AvaloniaXamlIlCompiler(new XamlIlTransformerConfiguration(_cecilTypeSystem,
localAssembly == null ? null : _cecilTypeSystem.FindAssembly(localAssembly.GetName().Name),
_cecilMappings, XamlIlXmlnsMappings.Resolve(_cecilTypeSystem, _cecilMappings),
AvaloniaXamlIlLanguage.CustomValueConverter),
_cecilEmitMappings,
- _cecilTypeSystem.CreateTypeBuilder(contextDef));
+ _cecilTypeSystem.CreateTypeBuilder(contextDef))
+ {
+ DefaultCompileBindings = useCompiledBindingsByDefault
+ };
compiler.ParseAndCompile(xaml, uri.ToString(), tb, overrideType);
var asmPath = Path.Combine(_cecilEmitDir, safeUri + ".dll");
using(var f = File.Create(asmPath))
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
index f325e6e2d6..e601701d5c 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlX;
using XamlX.Ast;
@@ -21,20 +22,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
private AvaloniaXamlIlCompiler(TransformerConfiguration configuration, XamlLanguageEmitMappings emitMappings)
: base(configuration, emitMappings, true)
{
- void InsertAfter(params IXamlAstTransformer[] t)
+ void InsertAfter(params IXamlAstTransformer[] t)
=> Transformers.InsertRange(Transformers.FindIndex(x => x is T) + 1, t);
- void InsertBefore(params IXamlAstTransformer[] t)
+ void InsertBefore(params IXamlAstTransformer[] t)
=> Transformers.InsertRange(Transformers.FindIndex(x => x is T), t);
// Before everything else
-
+
Transformers.Insert(0, new XNameTransformer());
Transformers.Insert(1, new IgnoredDirectivesTransformer());
Transformers.Insert(2, _designTransformer = new AvaloniaXamlIlDesignPropertiesTransformer());
Transformers.Insert(3, _bindingTransformer = new AvaloniaBindingExtensionTransformer());
-
+
// Targeted
InsertBefore(
new AvaloniaXamlIlResolveClassesPropertiesTransformer(),
@@ -48,14 +49,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
InsertBefore(
new AvaloniaXamlIlControlThemeTransformer(),
new AvaloniaXamlIlSelectorTransformer(),
- new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
+ new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
new AvaloniaXamlIlBindingPathParser(),
new AvaloniaXamlIlPropertyPathTransformer(),
+ new AvaloniaXamlIlSetterTargetTypeMetadataTransformer(),
new AvaloniaXamlIlSetterTransformer(),
new AvaloniaXamlIlConstructorServiceProviderTransformer(),
new AvaloniaXamlIlTransitionsTypeMetadataTransformer(),
- new AvaloniaXamlIlResolveByNameMarkupExtensionReplacer()
+ new AvaloniaXamlIlResolveByNameMarkupExtensionReplacer(),
+ new AvaloniaXamlIlAssetIncludeTransformer()
);
+ InsertBefore(
+ new AvaloniaXamlIlOptionMarkupExtensionTransformer());
InsertAfter(
new XDataTypeTransformer());
@@ -87,14 +92,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_contextType = CreateContextType(contextTypeBuilder);
}
-
+
public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
XamlLanguageEmitMappings emitMappings,
IXamlType contextType) : this(configuration, emitMappings)
{
_contextType = contextType;
}
-
+
public const string PopulateName = "__AvaloniaXamlIlPopulate";
public const string BuildName = "__AvaloniaXamlIlBuild";
@@ -116,7 +121,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
{XamlNamespaces.Blend2008, XamlNamespaces.Blend2008}
});
-
+
var rootObject = (XamlAstObjectNode)parsed.Root;
var classDirective = rootObject.Children
@@ -131,8 +136,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
false) :
TypeReferenceResolver.ResolveType(CreateTransformationContext(parsed, true),
(XamlAstXmlTypeReference)rootObject.Type, true);
-
-
+
+
if (overrideRootType != null)
{
if (!rootType.Type.IsAssignableFrom(overrideRootType))
@@ -145,7 +150,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
Transform(parsed);
Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource);
-
+
}
public void OverrideRootType(XamlDocument doc, IXamlAstTypeReference newType)
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
index c8fced515d..b4999136a4 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
@@ -185,6 +185,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public static bool CustomValueConverter(AstTransformationContext context,
IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
{
+ if (node is AvaloniaXamlIlOptionMarkupExtensionTransformer.OptionsMarkupExtensionNode optionsNode)
+ {
+ if (optionsNode.ConvertToReturnType(context, type, out var newOptionsNode))
+ {
+ result = newOptionsNode;
+ return true;
+ }
+ }
+
if (!(node is XamlAstTextNode textNode))
{
result = null;
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
index d907bcbef9..64fdfe155d 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
@@ -48,10 +48,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try
{
var thickness = Thickness.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
-
+
return true;
}
catch
@@ -65,10 +65,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try
{
var point = Point.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
new[] { point.X, point.Y });
-
+
return true;
}
catch
@@ -76,16 +76,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
}
}
-
+
if (type.Equals(types.Vector))
{
try
{
var vector = Vector.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
new[] { vector.X, vector.Y });
-
+
return true;
}
catch
@@ -93,16 +93,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
}
}
-
+
if (type.Equals(types.Size))
{
try
{
var size = Size.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
new[] { size.Width, size.Height });
-
+
return true;
}
catch
@@ -110,16 +110,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
}
}
-
+
if (type.Equals(types.Matrix))
{
try
{
var matrix = Matrix.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });
-
+
return true;
}
catch
@@ -127,16 +127,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
}
}
-
+
if (type.Equals(types.CornerRadius))
{
try
{
var cornerRadius = CornerRadius.Parse(text);
-
+
result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
-
+
return true;
}
catch
@@ -144,7 +144,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
}
}
-
+
if (type.Equals(types.Color))
{
if (!Color.TryParse(text, out Color color))
@@ -165,9 +165,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try
{
var relativePoint = RelativePoint.Parse(text);
-
+
var relativePointTypeRef = new XamlAstClrTypeReference(node, types.RelativePoint, false);
-
+
result = new XamlAstNewClrObjectNode(node, relativePointTypeRef, types.RelativePointFullConstructor, new List
{
new XamlConstantNode(node, types.XamlIlTypes.Double, relativePoint.Point.X),
@@ -188,9 +188,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
try
{
var gridLength = GridLength.Parse(text);
-
+
result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);
-
+
return true;
}
catch
@@ -201,12 +201,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
if (type.Equals(types.Cursor))
{
- if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
+ if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, false, out var enumConstantNode))
{
var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);
result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List { enumConstantNode });
-
+
return true;
}
}
@@ -270,12 +270,33 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
+ if (type.Equals(types.Uri))
+ {
+ var uriText = text.Trim();
+
+ var kind = ((!uriText?.StartsWith("/") == true) ? UriKind.Absolute : UriKind.Relative);
+
+ if (string.IsNullOrWhiteSpace(uriText) || !Uri.TryCreate(uriText, kind, out var _))
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse text {uriText} as a {kind} uri.", node);
+ }
+ result = new XamlAstNewClrObjectNode(node
+ , new(node, types.Uri, false)
+ , types.UriConstructor
+ , new List()
+ {
+ new XamlConstantNode(node, context.Configuration.WellKnownTypes.String, uriText),
+ new XamlConstantNode(node, types.UriKind, (int)kind),
+ });
+ return true;
+ }
+
result = null;
return false;
}
private static bool ConvertDefinitionList(
- IXamlAstValueNode node,
+ IXamlAstValueNode node,
string text,
AvaloniaXamlIlWellKnownTypes types,
IXamlType listType,
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlAssetIncludeTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlAssetIncludeTransformer.cs
new file mode 100644
index 0000000000..377a9e72d9
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlAssetIncludeTransformer.cs
@@ -0,0 +1,93 @@
+using System.Linq;
+using XamlX;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.Transform;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+
+internal class AvaloniaXamlIlAssetIncludeTransformer : IXamlAstTransformer
+{
+ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
+ {
+ if (node is not XamlAstObjectNode objectNode
+ || (objectNode.Type.GetClrType() != context.GetAvaloniaTypes().StyleInclude
+ && objectNode.Type.GetClrType() != context.GetAvaloniaTypes().ResourceInclude))
+ {
+ return node;
+ }
+
+ var nodeTypeName = objectNode.Type.GetClrType().Name;
+
+ var sourceProperty = objectNode.Children.OfType().FirstOrDefault(n => n.Property.GetClrProperty().Name == "Source");
+ var directives = objectNode.Children.OfType().ToList();
+ if (sourceProperty is null
+ || objectNode.Children.Count != (directives.Count + 1))
+ {
+ throw new XamlParseException($"Unexpected property on the {nodeTypeName} node", node);
+ }
+
+ if (sourceProperty.Values.OfType().FirstOrDefault() is not { } sourceTextNode)
+ {
+ // TODO: make it a compiler warning
+ // Source value can be set with markup extension instead of a text node, we don't support it here yet.
+ return node;
+ }
+
+ var originalAssetPath = sourceTextNode.Text;
+ if (!(originalAssetPath.StartsWith("avares://") || originalAssetPath.StartsWith("/")))
+ {
+ return node;
+ }
+
+ var runtimeHelpers = context.GetAvaloniaTypes().RuntimeHelpers;
+ var markerMethodName = "Resolve" + nodeTypeName;
+ var markerMethod = runtimeHelpers.FindMethod(m => m.Name == markerMethodName && m.Parameters.Count == 3);
+ if (markerMethod is null)
+ {
+ throw new XamlParseException($"Marker method \"{markerMethodName}\" was not found for the \"{nodeTypeName}\" node", node);
+ }
+
+ return new XamlValueWithManipulationNode(
+ node,
+ new AssetIncludeMethodNode(node, markerMethod, originalAssetPath),
+ new XamlManipulationGroupNode(node, directives));
+ }
+
+ private class AssetIncludeMethodNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+ {
+ private readonly IXamlMethod _method;
+ private readonly string _originalAssetPath;
+
+ public AssetIncludeMethodNode(
+ IXamlAstNode original, IXamlMethod method, string originalAssetPath)
+ : base(original)
+ {
+ _method = method;
+ _originalAssetPath = originalAssetPath;
+ }
+
+ public IXamlAstTypeReference Type => new XamlAstClrTypeReference(this, _method.ReturnType, false);
+
+ public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ var absoluteSource = _originalAssetPath;
+ if (absoluteSource.StartsWith("/"))
+ {
+ // Avoid Uri class here to avoid potential problems with escaping.
+ // Keeping string as close to the original as possible.
+ var absoluteBaseUrl = context.RuntimeContext.BaseUrl;
+ absoluteSource = absoluteBaseUrl.Substring(0, absoluteBaseUrl.LastIndexOf('/')) + absoluteSource;
+ }
+
+ codeGen.Ldstr(absoluteSource);
+ codeGen.Ldc_I4(Line);
+ codeGen.Ldc_I4(Position);
+ codeGen.EmitCall(_method);
+
+ return XamlILNodeEmitResult.Type(0, _method.ReturnType);
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs
index a09e13389a..288574d116 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlMetadataRemover.cs
@@ -1,4 +1,3 @@
-using System.Linq;
using XamlX.Ast;
using XamlX.Transform;
@@ -8,8 +7,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
- if (node is AvaloniaXamlIlTargetTypeMetadataNode targetType)
- return targetType.Value;
+ while (node is AvaloniaXamlIlTargetTypeMetadataNode targetType)
+ node = targetType.Value;
return node;
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
new file mode 100644
index 0000000000..5004e594f7
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
@@ -0,0 +1,403 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Emit;
+using XamlX;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.Transform;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+
+internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransformer
+{
+ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
+ {
+ if (node is XamlMarkupExtensionNode
+ {
+ Value: XamlAstObjectNode { Type: XamlAstClrTypeReference { Type: { } type } } objectNode
+ } markupExtensionNode
+ && type.FindMethods(m => m.IsPublic && m.Parameters.Count is 1 or 2 && m.ReturnType == context.Configuration.WellKnownTypes.Boolean && m.Name == "ShouldProvideOption").ToArray() is { } methods
+ && methods.Any())
+ {
+ var optionAttribute = context.GetAvaloniaTypes().MarkupExtensionOptionAttribute;
+ var defaultOptionAttribute = context.GetAvaloniaTypes().MarkupExtensionDefaultOptionAttribute;
+
+ var typeArgument = type.GenericArguments?.FirstOrDefault();
+
+ IXamlAstValueNode defaultValue = null;
+ var values = new List();
+
+ if (objectNode.Arguments.FirstOrDefault() is { } argument)
+ {
+ var hasDefaultProp = objectNode.Type.GetClrType().GetAllProperties().Any(p =>
+ p.CustomAttributes.Any(a => a.Type == defaultOptionAttribute));
+ if (hasDefaultProp)
+ {
+ if (objectNode.Arguments.Count > 1)
+ {
+ throw new XamlParseException("Options MarkupExtensions allow only single argument", objectNode);
+ }
+
+ defaultValue = TransformNode(new[] { argument }, typeArgument, objectNode);
+ objectNode.Arguments.Remove(argument);
+ }
+ }
+
+ foreach (var extProp in objectNode.Children.OfType().ToArray())
+ {
+ if (!extProp.Values.Any())
+ {
+ continue;
+ }
+
+ var shouldRemoveProp = false;
+ var onObjs = extProp.Values.OfType()
+ .Where(o => o.Type.GetClrType() == context.GetAvaloniaTypes().OnExtensionType).ToArray();
+ if (onObjs.Any())
+ {
+ shouldRemoveProp = true;
+ foreach (var onObj in onObjs)
+ {
+ var optionsPropNode = onObj.Children.OfType()
+ .SingleOrDefault(v => v.Property.GetClrProperty().Name == "Options")
+ ?.Values.Single();
+ var options = (optionsPropNode as XamlAstTextNode)?.Text?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
+ ?? Array.Empty();
+ if (options.Length == 0)
+ {
+ throw new XamlParseException("On.Options string must be set", onObj);
+ }
+
+ var content = onObj.Children.OfType()
+ .SingleOrDefault(v => v.Property.GetClrProperty().Name == "Content");
+ if (content is null)
+ {
+ throw new XamlParseException("On content object must be set", onObj);
+ }
+
+ var propertiesSet = options
+ .Select(o => type.GetAllProperties()
+ .FirstOrDefault(p => o.Equals(p.Name, StringComparison.Ordinal))
+ ?? throw new XamlParseException($"Property \"{o}\" wasn't found on the \"{type.Name}\" type", onObj))
+ .ToArray();
+ foreach (var propertySet in propertiesSet)
+ {
+ AddBranchNode(content.Values, propertySet.CustomAttributes, content);
+ }
+ }
+ }
+ else
+ {
+ shouldRemoveProp = AddBranchNode(extProp.Values, extProp.Property.GetClrProperty().CustomAttributes, extProp);
+ }
+
+ if (shouldRemoveProp)
+ {
+ objectNode.Children.Remove(extProp);
+ }
+ }
+
+ if (defaultValue is null && !values.Any())
+ {
+ throw new XamlParseException("Options markup extension requires at least one option to be set", objectNode);
+ }
+
+ return new OptionsMarkupExtensionNode(
+ markupExtensionNode, values.ToArray(), defaultValue,
+ context.Configuration.TypeMappings.ServiceProvider);
+
+ bool AddBranchNode(
+ IReadOnlyCollection valueNodes,
+ IReadOnlyCollection propAttributes,
+ IXamlLineInfo li)
+ {
+ var transformed = TransformNode(valueNodes, typeArgument, li);
+ if (propAttributes.FirstOrDefault(a => a.Type == defaultOptionAttribute) is { } defAttr)
+ {
+ defaultValue = transformed;
+ return true;
+ }
+ else if (propAttributes.FirstOrDefault(a => a.Type == optionAttribute) is { } optAttr)
+ {
+ var option = optAttr.Parameters.Single();
+ if (option is null)
+ {
+ throw new XamlParseException("MarkupExtension option must not be null", li);
+ }
+
+ var optionAsString = option.ToString();
+ IXamlAstValueNode optionNode = null;
+ foreach (var method in methods)
+ {
+ try
+ {
+ var targetType = method.Parameters.Last();
+ if (targetType.FullName == "System.Type")
+ {
+ if (option is IXamlType typeOption)
+ {
+ optionNode = new XamlTypeExtensionNode(li,
+ new XamlAstClrTypeReference(li, typeOption, false), targetType);
+ }
+ }
+ else if (targetType == context.Configuration.WellKnownTypes.String)
+ {
+ optionNode = new XamlConstantNode(li, targetType, optionAsString);
+ }
+ else if (targetType.IsEnum)
+ {
+ if (TypeSystemHelpers.TryGetEnumValueNode(targetType, optionAsString, li, false,
+ out var enumConstantNode))
+ {
+ optionNode = enumConstantNode;
+ }
+ }
+ else if (TypeSystemHelpers.ParseConstantIfTypeAllows(optionAsString, targetType, li,
+ out var constantNode))
+ {
+ optionNode = constantNode;
+ }
+ }
+ catch (FormatException)
+ {
+ // try next method overload
+ }
+
+ if (optionNode is not null)
+ {
+ values.Add(new OptionsMarkupExtensionBranch(optionNode, transformed, method));
+ return true;
+ }
+ }
+
+ throw new XamlParseException($"Option value \"{optionAsString}\" is not assignable to any of existing ShouldProvideOption methods", li);
+ }
+
+ return false;
+ }
+ }
+
+ return node;
+
+ IXamlAstValueNode TransformNode(
+ IReadOnlyCollection values,
+ IXamlType suggestedType,
+ IXamlLineInfo line)
+ {
+ if (suggestedType is not null)
+ {
+ values = values
+ .Select(v => XamlTransformHelpers
+ .TryGetCorrectlyTypedValue(context, v, suggestedType, out var converted)
+ ? converted : v)
+ .ToArray();
+ }
+
+ if (values.Count > 1)
+ {
+ throw new XamlParseException("Options markup extension supports only a singular value", line);
+ }
+
+ return values.Single();
+ }
+ }
+
+ internal sealed class OptionsMarkupExtensionNode : XamlMarkupExtensionNode, IXamlAstValueNode
+ {
+ private readonly IXamlType _contextParameter;
+
+ public OptionsMarkupExtensionNode(
+ XamlMarkupExtensionNode original,
+ OptionsMarkupExtensionBranch[] branches,
+ IXamlAstValueNode defaultNode,
+ IXamlType contextParameter)
+ : base(
+ original.Value,
+ new OptionsMarkupExtensionMethod(new OptionsMarkupExtensionNodesContainer(branches, defaultNode), original.Value.Type.GetClrType(), contextParameter),
+ original.Value)
+ {
+ _contextParameter = contextParameter;
+ }
+
+ public new OptionsMarkupExtensionMethod ProvideValue => (OptionsMarkupExtensionMethod)base.ProvideValue;
+
+ IXamlAstTypeReference IXamlAstValueNode.Type => new XamlAstClrTypeReference(this, ProvideValue.ReturnType, false);
+
+ public override void VisitChildren(IXamlAstVisitor visitor)
+ {
+ ProvideValue.ExtensionNodeContainer.Visit(visitor);
+ base.VisitChildren(visitor);
+ }
+
+ public bool ConvertToReturnType(AstTransformationContext context, IXamlType type, out OptionsMarkupExtensionNode res)
+ {
+ IXamlAstValueNode convertedDefaultNode = null;
+
+ if (ProvideValue.ExtensionNodeContainer.DefaultNode is { } defaultNode)
+ {
+ if (!XamlTransformHelpers.TryGetCorrectlyTypedValue(context, defaultNode, type, out convertedDefaultNode))
+ {
+ res = null;
+ return false;
+ }
+ }
+
+ var convertedBranches = ProvideValue.ExtensionNodeContainer.Branches.Select(b => XamlTransformHelpers
+ .TryGetCorrectlyTypedValue(context, b.Value, type, out var convertedValue) ?
+ new OptionsMarkupExtensionBranch(b.Option, convertedValue, b.ConditionMethod) :
+ null).ToArray();
+ if (convertedBranches.Any(b => b is null))
+ {
+ res = null;
+ return false;
+ }
+
+ res = new OptionsMarkupExtensionNode(this, convertedBranches, convertedDefaultNode, _contextParameter);
+ return true;
+ }
+ }
+
+ internal sealed class OptionsMarkupExtensionNodesContainer : XamlAstNode
+ {
+ public OptionsMarkupExtensionNodesContainer(
+ OptionsMarkupExtensionBranch[] branches,
+ IXamlAstValueNode defaultNode) : base(branches.FirstOrDefault()?.Value ?? defaultNode)
+ {
+ Branches = branches;
+ DefaultNode = defaultNode;
+ }
+
+ public OptionsMarkupExtensionBranch[] Branches { get; }
+ public IXamlAstValueNode DefaultNode { get; private set; }
+
+ public override void VisitChildren(IXamlAstVisitor visitor)
+ {
+ VisitList(Branches, visitor);
+ DefaultNode = (IXamlAstValueNode)DefaultNode?.Visit(visitor);
+ }
+
+ public IXamlType GetReturnType()
+ {
+ var types = Branches.Select(b => b.Value.Type);
+ if (DefaultNode?.Type is { } type)
+ {
+ types = types.Concat(new [] { type });
+ }
+ return types.Select(t => t.GetClrType()).ToArray().GetCommonBaseClass();
+ }
+ }
+
+ internal sealed class OptionsMarkupExtensionBranch : XamlAstNode
+ {
+ public OptionsMarkupExtensionBranch(IXamlAstValueNode option, IXamlAstValueNode value, IXamlMethod conditionMethod) : base(value)
+ {
+ Option = option;
+ Value = value;
+ ConditionMethod = conditionMethod;
+ }
+
+ public IXamlAstValueNode Option { get; set; }
+ public IXamlAstValueNode Value { get; set; }
+ public IXamlMethod ConditionMethod { get; }
+
+ public bool HasContext => ConditionMethod.Parameters.Count > 1;
+
+ public override void VisitChildren(IXamlAstVisitor visitor)
+ {
+ Option = (IXamlAstValueNode)Option.Visit(visitor);
+ Value = (IXamlAstValueNode)Value.Visit(visitor);
+ }
+ }
+
+ internal sealed class OptionsMarkupExtensionMethod : IXamlCustomEmitMethodWithContext
+ {
+ public OptionsMarkupExtensionMethod(
+ OptionsMarkupExtensionNodesContainer extensionNodeContainer,
+ IXamlType declaringType,
+ IXamlType contextParameter)
+ {
+ ExtensionNodeContainer = extensionNodeContainer;
+ DeclaringType = declaringType;
+ Parameters = extensionNodeContainer.Branches.Any(c => c.HasContext) ?
+ new[] { contextParameter } :
+ Array.Empty();
+ }
+
+ public OptionsMarkupExtensionNodesContainer ExtensionNodeContainer { get; }
+
+ public string Name => "ProvideValue";
+ public bool IsPublic => true;
+ public bool IsStatic => false;
+ public IXamlType ReturnType => ExtensionNodeContainer.GetReturnType();
+ public IReadOnlyList Parameters { get; }
+ public IXamlType DeclaringType { get; }
+ public IXamlMethod MakeGenericMethod(IReadOnlyList typeArguments) => throw new NotImplementedException();
+ public IReadOnlyList CustomAttributes => Array.Empty();
+
+ public void EmitCall(XamlEmitContext context, IXamlILEmitter codeGen)
+ {
+ // At this point this extension will be called from MarkupExtensionEmitter.
+ // Since it's a "fake" method, we share stack and locals with parent method.
+ // Real ProvideValue method would pop 2 parameters from the stack and return one. This method should do the same.
+ // At this point we will have on stack:
+ // - context (if parameters > 1)
+ // - markup ext "@this" instance (always)
+ // We always pop context from the stack, as this method decide by itself either context is needed.
+ // We store "@this" as a local variable. But only if any conditional method is an instance method.
+ IXamlLocal @this = null;
+ if (Parameters.Count > 0)
+ {
+ codeGen.Pop();
+ }
+ if (ExtensionNodeContainer.Branches.Any(b => !b.ConditionMethod.IsStatic))
+ {
+ codeGen.Stloc(@this = codeGen.DefineLocal(DeclaringType));
+ }
+ else
+ {
+ codeGen.Pop();
+ }
+
+ // Iterate over all branches and push prepared locals into the stack if needed.
+ var ret = codeGen.DefineLabel();
+ foreach (var branch in ExtensionNodeContainer.Branches)
+ {
+ var next = codeGen.DefineLabel();
+ if (branch.HasContext)
+ {
+ codeGen.Ldloc(context.ContextLocal);
+ }
+ if (!branch.ConditionMethod.IsStatic)
+ {
+ codeGen.Ldloc(@this);
+ }
+ context.Emit(branch.Option, codeGen, branch.Option.Type.GetClrType());
+ codeGen.EmitCall(branch.ConditionMethod);
+ codeGen.Brfalse(next);
+
+ context.Emit(branch.Value, codeGen, branch.Value.Type.GetClrType());
+ codeGen.Br(ret);
+ codeGen.MarkLabel(next);
+ }
+
+ if (ExtensionNodeContainer.DefaultNode is {} defaultNode)
+ {
+ // Nop is needed, otherwise Label wouldn't be set on nested CALL op (limitation of our IL validator).
+ codeGen.Emit(OpCodes.Nop);
+ context.Emit(defaultNode, codeGen, defaultNode.Type.GetClrType());
+ }
+ else
+ {
+ codeGen.EmitDefault(ReturnType);
+ }
+
+ codeGen.MarkLabel(ret);
+ }
+
+ public bool Equals(IXamlMethod other) => ReferenceEquals(this, other);
+ }
+}
+
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
index 70209fb3ad..ba0da4fbe0 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
@@ -128,13 +128,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
break;
}
case SelectorGrammar.ChildSyntax child:
- result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Child);
+ result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Child);
break;
case SelectorGrammar.DescendantSyntax descendant:
- result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Descendant);
+ result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Descendant);
break;
case SelectorGrammar.TemplateSyntax template:
- result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Template);
+ result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.CombinatorSelectorType.Template);
break;
case SelectorGrammar.NotSyntax not:
result = new XamlIlNotSelector(result, Create(not.Argument, typeResolver));
@@ -186,18 +186,42 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
=> TypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));
pn.Values[0] = selector;
- return new AvaloniaXamlIlTargetTypeMetadataNode(on,
+ var templateType = GetLastTemplateTypeFromSelector(selector);
+
+ var styleNode = new AvaloniaXamlIlTargetTypeMetadataNode(on,
new XamlAstClrTypeReference(selector, selector.TargetType, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
+
+ return templateType switch
+ {
+ null => styleNode,
+ _ => new AvaloniaXamlIlTargetTypeMetadataNode(styleNode,
+ new XamlAstClrTypeReference(styleNode, templateType, false),
+ AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.ControlTemplate)
+ };
}
- }
+ private static IXamlType GetLastTemplateTypeFromSelector(XamlIlSelectorNode node)
+ {
+ while (node is not null)
+ {
+ if (node is XamlIlCombinatorSelector
+ {
+ SelectorType: XamlIlCombinatorSelector.CombinatorSelectorType.Template
+ })
+ {
+ return node.Previous.TargetType;
+ }
+ node = node.Previous;
+ }
+ return null;
+ }
+ }
-
abstract class XamlIlSelectorNode : XamlAstNode, IXamlAstValueNode, IXamlAstEmitableNode
{
- protected XamlIlSelectorNode Previous { get; }
+ internal XamlIlSelectorNode Previous { get; }
public abstract IXamlType TargetType { get; }
public XamlIlSelectorNode(XamlIlSelectorNode previous,
@@ -289,19 +313,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class XamlIlCombinatorSelector : XamlIlSelectorNode
{
- private readonly SelectorType _type;
+ private readonly CombinatorSelectorType _type;
- public enum SelectorType
+ public enum CombinatorSelectorType
{
Child,
Descendant,
Template
}
- public XamlIlCombinatorSelector(XamlIlSelectorNode previous, SelectorType type) : base(previous)
+ public XamlIlCombinatorSelector(XamlIlSelectorNode previous, CombinatorSelectorType type) : base(previous)
{
_type = type;
}
+ public CombinatorSelectorType SelectorType => _type;
public override IXamlType TargetType => null;
protected override void DoEmit(XamlEmitContext context, IXamlILEmitter codeGen)
{
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTargetTypeMetadataTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTargetTypeMetadataTransformer.cs
new file mode 100644
index 0000000000..ebc6c01ba8
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTargetTypeMetadataTransformer.cs
@@ -0,0 +1,34 @@
+using System.Linq;
+using XamlX;
+using XamlX.Ast;
+using XamlX.Transform;
+using XamlX.Transform.Transformers;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+
+internal class AvaloniaXamlIlSetterTargetTypeMetadataTransformer : IXamlAstTransformer
+{
+ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
+ {
+ if (node is XamlAstObjectNode on
+ && on.Children.FirstOrDefault(c => c is XamlAstXmlDirective
+ {
+ Namespace: XamlNamespaces.Xaml2006,
+ Name: "SetterTargetType"
+ }) is { } typeDirective)
+ {
+ var value = ((XamlAstXmlDirective)typeDirective).Values.Single();
+ var type = value is XamlTypeExtensionNode typeNode ? typeNode.Value
+ : value is XamlAstTextNode tn ? TypeReferenceResolver.ResolveType(context, tn.Text, false, tn, true)
+ : null;
+ on.Children.Remove(typeDirective);
+
+ if (type is null)
+ {
+ throw new XamlParseException("Unable to resolve SetterTargetType type", typeDirective);
+ }
+ return new AvaloniaXamlIlTargetTypeMetadataNode(on, type, AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
+ }
+ return node;
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
index ceaec972f6..5a6fd8246d 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+using XamlX;
using XamlX.Ast;
using XamlX.Emit;
using XamlX.IL;
@@ -8,7 +9,6 @@ using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
- using XamlParseException = XamlX.XamlParseException;
class AvaloniaXamlIlSetterTransformer : IXamlAstTransformer
{
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
@@ -17,10 +17,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& on.Type.GetClrType().FullName == "Avalonia.Styling.Setter"))
return node;
- var targetTypeNode = context.ParentNodes()
+ IXamlType targetType = null;
+ IXamlLineInfo lineInfo = null;
+
+ var styleParent = context.ParentNodes()
.OfType()
- .FirstOrDefault(x => x.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style) ??
- throw new XamlParseException("Can not find parent Style Selector or ControlTemplate TargetType", node);
+ .FirstOrDefault(x => x.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
+
+ if (styleParent != null)
+ {
+ targetType = styleParent.TargetType.GetClrType()
+ ?? throw new XamlParseException("Can not find parent Style Selector or ControlTemplate TargetType. If setter is not part of the style, you can set x:SetterTargetType directive on its parent.", node);
+ lineInfo = on;
+ }
+
+ if (targetType == null)
+ {
+ throw new XamlParseException("Could not determine target type of Setter", node);
+ }
IXamlType propType = null;
var property = @on.Children.OfType()
@@ -31,9 +45,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (propertyName == null)
throw new XamlParseException("Setter.Property must be a string", node);
-
var avaloniaPropertyNode = XamlIlAvaloniaPropertyHelper.CreateNode(context, propertyName,
- new XamlAstClrTypeReference(targetTypeNode, targetTypeNode.TargetType.GetClrType(), false), property.Values[0]);
+ new XamlAstClrTypeReference(lineInfo, targetType, false), property.Values[0]);
property.Values = new List {avaloniaPropertyNode};
propType = avaloniaPropertyNode.AvaloniaPropertyType;
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index dbfbe0e070..dd37ae6c93 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -9,6 +9,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class AvaloniaXamlIlWellKnownTypes
{
+ public IXamlType RuntimeHelpers { get; }
public IXamlType AvaloniaObject { get; }
public IXamlType IAvaloniaObject { get; }
public IXamlType BindingPriority { get; }
@@ -29,6 +30,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType AssignBindingAttribute { get; }
public IXamlType DependsOnAttribute { get; }
public IXamlType DataTypeAttribute { get; }
+ public IXamlType MarkupExtensionOptionAttribute { get; }
+ public IXamlType MarkupExtensionDefaultOptionAttribute { get; }
+ public IXamlType OnExtensionType { get; }
public IXamlType UnsetValueType { get; }
public IXamlType StyledElement { get; }
public IXamlType IStyledElement { get; }
@@ -98,12 +102,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType TextDecorations { get; }
public IXamlType TextTrimming { get; }
public IXamlType ISetter { get; }
+ public IXamlType IStyle { get; }
+ public IXamlType StyleInclude { get; }
+ public IXamlType ResourceInclude { get; }
public IXamlType IResourceDictionary { get; }
public IXamlType ResourceDictionary { get; }
public IXamlMethod ResourceDictionaryDeferredAdd { get; }
+ public IXamlType UriKind { get; }
+ public IXamlConstructor UriConstructor { get; }
public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
{
+ RuntimeHelpers = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
+
XamlIlTypes = cfg.WellKnownTypes;
AvaloniaObject = cfg.TypeSystem.GetType("Avalonia.AvaloniaObject");
IAvaloniaObject = cfg.TypeSystem.GetType("Avalonia.IAvaloniaObject");
@@ -125,6 +136,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AssignBindingAttribute = cfg.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
DependsOnAttribute = cfg.TypeSystem.GetType("Avalonia.Metadata.DependsOnAttribute");
DataTypeAttribute = cfg.TypeSystem.GetType("Avalonia.Metadata.DataTypeAttribute");
+ MarkupExtensionOptionAttribute = cfg.TypeSystem.GetType("Avalonia.Metadata.MarkupExtensionOptionAttribute");
+ MarkupExtensionDefaultOptionAttribute = cfg.TypeSystem.GetType("Avalonia.Metadata.MarkupExtensionDefaultOptionAttribute");
+ OnExtensionType = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.On");
AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject,
AvaloniaProperty,
IBinding, cfg.WellKnownTypes.Object);
@@ -221,12 +235,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
TextDecorations = cfg.TypeSystem.GetType("Avalonia.Media.TextDecorations");
TextTrimming = cfg.TypeSystem.GetType("Avalonia.Media.TextTrimming");
ISetter = cfg.TypeSystem.GetType("Avalonia.Styling.ISetter");
+ IStyle = cfg.TypeSystem.GetType("Avalonia.Styling.IStyle");
+ StyleInclude = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Styling.StyleInclude");
+ ResourceInclude = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Styling.ResourceInclude");
IResourceDictionary = cfg.TypeSystem.GetType("Avalonia.Controls.IResourceDictionary");
ResourceDictionary = cfg.TypeSystem.GetType("Avalonia.Controls.ResourceDictionary");
ResourceDictionaryDeferredAdd = ResourceDictionary.FindMethod("AddDeferred", XamlIlTypes.Void, true, XamlIlTypes.Object,
cfg.TypeSystem.GetType("System.Func`2").MakeGenericType(
cfg.TypeSystem.GetType("System.IServiceProvider"),
XamlIlTypes.Object));
+ UriKind = cfg.TypeSystem.GetType("System.UriKind");
+ UriConstructor = Uri.GetConstructor(new List() { cfg.WellKnownTypes.String, UriKind });
}
}
@@ -239,7 +258,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx.Configuration));
return rv;
}
-
+
public static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlEmitContext ctx)
{
if (ctx.TryGetItem(out var rv))
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs
index e76e2cd46e..affd3aa42b 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs
@@ -59,14 +59,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
var field = _builder.DefineField(types.IPropertyInfo, name + "!Field", false, true);
- void Load(IXamlMethod m, IXamlILEmitter cg)
+ void Load(IXamlMethod m, IXamlILEmitter cg, bool passThis)
{
- cg
- .Ldarg_0();
- if (m.DeclaringType.IsValueType)
- cg.Unbox(m.DeclaringType);
- else
- cg.Castclass(m.DeclaringType);
+ if (passThis)
+ {
+ cg
+ .Ldarg_0();
+ if (m.DeclaringType.IsValueType)
+ cg.Unbox(m.DeclaringType);
+ else
+ cg.Castclass(m.DeclaringType);
+ }
foreach (var indexerArg in indexerArguments)
{
@@ -80,7 +83,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
new[] {types.XamlIlTypes.Object}, name + "!Getter", false, true, false);
if (getter != null)
{
- Load(property.Getter, getter.Generator);
+ Load(property.Getter, getter.Generator, !property.Getter.IsStatic);
getter.Generator.EmitCall(property.Getter);
if (property.Getter.ReturnType.IsValueType)
@@ -95,7 +98,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
name + "!Setter", false, true, false);
if (setter != null)
{
- Load(property.Setter, setter.Generator);
+ Load(property.Setter, setter.Generator, !property.Getter.IsStatic);
setter.Generator.Ldarg(1);
if (property.Setter.Parameters[0].IsValueType)
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
index c1c0594ec2..cd3682c615 160000
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
@@ -1 +1 @@
-Subproject commit c1c0594ec2c35b08988183b1a5b3e34dfa19179d
+Subproject commit cd3682c61577a3518de765f7938295d98ff9808c
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index d0c39f0289..b5ba49ce2c 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -9,6 +9,7 @@
CS1591
+
@@ -28,10 +29,11 @@
+
+
+
-
-
@@ -40,6 +42,8 @@
+
+
@@ -68,4 +72,8 @@
+
+
+
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
index e5c6b72d12..578af64abb 100644
--- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
@@ -1,8 +1,5 @@
using System;
using System.IO;
-using System.Reflection;
-using System.Text;
-using Avalonia.Markup.Xaml.XamlIl;
using Avalonia.Platform;
namespace Avalonia.Markup.Xaml
@@ -14,7 +11,7 @@ namespace Avalonia.Markup.Xaml
{
public interface IRuntimeXamlLoader
{
- object Load(Stream stream, Assembly localAsm, object o, Uri baseUri, bool designMode);
+ object Load(Stream stream, RuntimeXamlLoaderConfiguration configuration);
}
///
@@ -67,7 +64,11 @@ namespace Avalonia.Markup.Xaml
using (var stream = asset.stream)
{
var absoluteUri = uri.IsAbsoluteUri ? uri : new Uri(baseUri, uri);
- return runtimeLoader.Load(stream, asset.assembly, null, absoluteUri, false);
+ return runtimeLoader.Load(stream, new RuntimeXamlLoaderConfiguration
+ {
+ LocalAssembly = asset.assembly,
+ BaseUri = absoluteUri
+ });
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/TimeSpanTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/TimeSpanTypeConverter.cs
index 1e42a46875..1b6fbcef5c 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Converters/TimeSpanTypeConverter.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/TimeSpanTypeConverter.cs
@@ -15,7 +15,7 @@ namespace Avalonia.Markup.Xaml.Converters
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var valueStr = (string)value;
- if (!valueStr.Contains(":"))
+ if (!valueStr.Contains(':'))
{
// shorthand seconds format (ie. "0.25")
var secs = double.Parse(valueStr, CultureInfo.InvariantCulture);
@@ -25,4 +25,4 @@ namespace Avalonia.Markup.Xaml.Converters
return base.ConvertFrom(context, culture, value);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
index 970cc767f7..8339fe8e38 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
@@ -124,7 +124,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
{
if (_dependsOnProperties is { Count: > 0 } && _reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
{
- WeakEventHandlerManager.Unsubscribe(
+ WeakEventHandlerManager.Unsubscribe(
inpc,
nameof(INotifyPropertyChanged.PropertyChanged),
OnNotifyPropertyChanged);
@@ -145,7 +145,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
{
if (_dependsOnProperties is { Count:>0 } && _reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
{
- WeakEventHandlerManager.Subscribe(
+ WeakEventHandlerManager.Subscribe(
inpc,
nameof(INotifyPropertyChanged.PropertyChanged),
OnNotifyPropertyChanged);
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
index f78d4867ff..a49a7a36d4 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
@@ -75,8 +75,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
}
internal IEnumerable Elements => _elements;
-
- internal SourceMode SourceMode => _elements.Count > 0 && _elements[0] is IControlSourceBindingPathElement ? SourceMode.Control : SourceMode.Data;
+
+ internal SourceMode SourceMode => _elements.OfType().Any()
+ ? SourceMode.Control : SourceMode.Data;
internal object RawSource { get; }
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/On.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/On.cs
new file mode 100644
index 0000000000..0752ab43b5
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/On.cs
@@ -0,0 +1,15 @@
+#nullable enable
+using System.Collections.Generic;
+using Avalonia.Metadata;
+
+namespace Avalonia.Markup.Xaml.MarkupExtensions;
+
+public class On
+{
+ public IReadOnlyList Options { get; } = new List();
+
+ [Content]
+ public TReturn? Content { get; set; }
+}
+
+public class On : On
public class StyleInclude : IStyle, IResourceProvider
{
- private readonly Uri _baseUri;
+ private readonly Uri? _baseUri;
private IStyle[]? _loaded;
private bool _isLoading;
@@ -20,7 +20,7 @@ namespace Avalonia.Markup.Xaml.Styling
/// Initializes a new instance of the class.
///
/// The base URL for the XAML context.
- public StyleInclude(Uri baseUri)
+ public StyleInclude(Uri? baseUri)
{
_baseUri = baseUri;
}
@@ -82,8 +82,6 @@ namespace Avalonia.Markup.Xaml.Styling
}
}
- public SelectorMatchResult TryAttach(IStyleable target, object? host) => Loaded.TryAttach(target, host);
-
public bool TryGetResource(object key, out object? value)
{
if (!_isLoading)
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
index 168b9835dd..f547888d6e 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
@@ -1,11 +1,15 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Data;
+using Avalonia.Markup.Xaml.MarkupExtensions;
+using Avalonia.Markup.Xaml.Styling;
+using Avalonia.Platform;
+using Avalonia.Styling;
+
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedParameter.Global
@@ -13,12 +17,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
public static class XamlIlRuntimeHelpers
{
+ public static IStyle ResolveStyleInclude(string absoluteSource, int line, int position)
+ {
+ return new StyleInclude((Uri)null) { Source = new Uri(absoluteSource) }.Loaded;
+ }
+
+ public static IResourceDictionary ResolveResourceInclude(string absoluteSource, int line, int position)
+ {
+ return new ResourceInclude((Uri)null) { Source = new Uri(absoluteSource) }.Loaded;
+ }
+
public static Func DeferredTransformationFactoryV1(Func builder,
IServiceProvider provider)
{
return DeferredTransformationFactoryV2(builder, provider);
}
-
+
public static Func DeferredTransformationFactoryV2(Func builder,
IServiceProvider provider)
{
@@ -31,7 +45,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
var scope = parentScope != null ? new ChildNameScope(parentScope) : (INameScope)new NameScope();
var obj = builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject, scope));
scope.Complete();
-
+
if(typeof(T) == typeof(IControl))
return new ControlTemplateResult((IControl)obj, scope);
@@ -107,9 +121,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
throw new ArgumentException("Don't know what to do with " + value.GetType());
}
- public static IServiceProvider CreateInnerServiceProviderV1(IServiceProvider compiled)
+ public static IServiceProvider CreateInnerServiceProviderV1(IServiceProvider compiled)
=> new InnerServiceProvider(compiled);
-
+
class InnerServiceProvider : IServiceProvider
{
private readonly IServiceProvider _compiledProvider;
@@ -136,7 +150,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
_nsInfo = nsInfo;
}
-
+
public Type Resolve(string qualifiedTypeName)
{
var sp = qualifiedTypeName.Split(new[] {':'}, 2);
@@ -166,22 +180,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
return new RootServiceProvider(new NameScope());
}
#line default
-
+
class RootServiceProvider : IServiceProvider, IAvaloniaXamlIlParentStackProvider
{
private readonly INameScope _nameScope;
+ private readonly IRuntimePlatform _runtimePlatform;
public RootServiceProvider(INameScope nameScope)
{
_nameScope = nameScope;
+ _runtimePlatform = AvaloniaLocator.Current.GetService();
}
-
+
public object GetService(Type serviceType)
{
if (serviceType == typeof(INameScope))
return _nameScope;
if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider))
return this;
+ if (serviceType == typeof(IRuntimePlatform))
+ return _runtimePlatform ?? throw new KeyNotFoundException($"{nameof(IRuntimePlatform)} was not registered");
+
return null;
}
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
index 439bc15243..21c0d97c74 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
@@ -168,7 +168,11 @@ namespace Avalonia.Markup.Parsers
}
}
- private static State ParseAttachedProperty(ref CharacterReader r, List nodes)
+ private static State ParseAttachedProperty(
+#if NET7SDK
+ scoped
+#endif
+ ref CharacterReader r, List nodes)
{
var (ns, owner) = ParseTypeName(ref r);
@@ -318,7 +322,11 @@ namespace Avalonia.Markup.Parsers
return State.AfterMember;
}
- private static TypeName ParseTypeName(ref CharacterReader r)
+ private static TypeName ParseTypeName(
+#if NET7SDK
+ scoped
+#endif
+ ref CharacterReader r)
{
ReadOnlySpan ns, typeName;
ns = ReadOnlySpan.Empty;
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
index 16856e674d..4d6d16a3ce 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
@@ -376,28 +376,28 @@ namespace Avalonia.Markup.Parsers
if (r.Peek == 'o')
{
- var constArg = r.TakeUntil(')').ToString().Trim();
- if (constArg.Equals("odd", StringComparison.Ordinal))
+ var constArg = r.TakeUntil(')').Trim();
+ if (constArg.SequenceEqual("odd".AsSpan()))
{
step = 2;
offset = 1;
}
else
{
- throw new ExpressionParseException(r.Position, $"Expected nth-child(odd). Actual '{constArg}'.");
+ throw new ExpressionParseException(r.Position, $"Expected nth-child(odd). Actual '{constArg.ToString()}'.");
}
}
else if (r.Peek == 'e')
{
- var constArg = r.TakeUntil(')').ToString().Trim();
- if (constArg.Equals("even", StringComparison.Ordinal))
+ var constArg = r.TakeUntil(')').Trim();
+ if (constArg.SequenceEqual("even".AsSpan()))
{
step = 2;
offset = 0;
}
else
{
- throw new ExpressionParseException(r.Position, $"Expected nth-child(even). Actual '{constArg}'.");
+ throw new ExpressionParseException(r.Position, $"Expected nth-child(even). Actual '{constArg.ToString()}'.");
}
}
else
@@ -405,7 +405,7 @@ namespace Avalonia.Markup.Parsers
r.SkipWhitespace();
var stepOrOffset = 0;
- var stepOrOffsetStr = r.TakeWhile(c => char.IsDigit(c) || c == '-' || c == '+').ToString();
+ var stepOrOffsetStr = r.TakeWhile(c => char.IsDigit(c) || c == '-' || c == '+');
if (stepOrOffsetStr.Length == 0
|| (stepOrOffsetStr.Length == 1
&& stepOrOffsetStr[0] == '+'))
@@ -417,7 +417,7 @@ namespace Avalonia.Markup.Parsers
{
stepOrOffset = -1;
}
- else if (!int.TryParse(stepOrOffsetStr.ToString(), out stepOrOffset))
+ else if (!stepOrOffsetStr.TryParseInt(out stepOrOffset))
{
throw new ExpressionParseException(r.Position, "Couldn't parse nth-child step or offset value. Integer was expected.");
}
@@ -462,7 +462,7 @@ namespace Avalonia.Markup.Parsers
r.SkipWhitespace();
if (sign != 0
- && !int.TryParse(r.TakeUntil(')').ToString(), out offset))
+ && !r.TakeUntil(')').TryParseInt(out offset))
{
throw new ExpressionParseException(r.Position, "Couldn't parse nth-child offset value. Integer was expected.");
}
diff --git a/src/Shared/StringCompatibilityExtensions.cs b/src/Shared/StringCompatibilityExtensions.cs
new file mode 100644
index 0000000000..7c894dba97
--- /dev/null
+++ b/src/Shared/StringCompatibilityExtensions.cs
@@ -0,0 +1,12 @@
+using System.Runtime.CompilerServices;
+
+namespace System;
+
+#if !NET6_0_OR_GREATER
+internal static class StringCompatibilityExtensions
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains(this string str, char search) =>
+ str.Contains(search.ToString());
+}
+#endif
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 99ab60d1ac..6dcafdcfd7 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -35,9 +35,9 @@ namespace Avalonia.Skia
private GRContext _grContext;
public GRContext GrContext => _grContext;
private ISkiaGpu _gpu;
- private readonly SKPaint _strokePaint = new SKPaint();
- private readonly SKPaint _fillPaint = new SKPaint();
- private readonly SKPaint _boxShadowPaint = new SKPaint();
+ private readonly SKPaint _strokePaint = SKPaintCache.Get();
+ private readonly SKPaint _fillPaint = SKPaintCache.Get();
+ private readonly SKPaint _boxShadowPaint = SKPaintCache.Get();
private static SKShader s_acrylicNoiseShader;
private readonly ISkiaGpuRenderSession _session;
private bool _leased = false;
@@ -187,17 +187,13 @@ namespace Avalonia.Skia
var s = sourceRect.ToSKRect();
var d = destRect.ToSKRect();
- using (var paint =
- new SKPaint
- {
- Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity))
- })
- {
- paint.FilterQuality = bitmapInterpolationMode.ToSKFilterQuality();
- paint.BlendMode = _currentBlendingMode.ToSKBlendMode();
+ var paint = SKPaintCache.Get();
+ paint.Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity));
+ paint.FilterQuality = bitmapInterpolationMode.ToSKFilterQuality();
+ paint.BlendMode = _currentBlendingMode.ToSKBlendMode();
- drawableImage.Draw(this, s, d, paint);
- }
+ drawableImage.Draw(this, s, d, paint);
+ SKPaintCache.ReturnReset(paint);
}
///
@@ -561,6 +557,11 @@ namespace Avalonia.Skia
CheckLease();
try
{
+ // Return leased paints.
+ SKPaintCache.ReturnReset(_strokePaint);
+ SKPaintCache.ReturnReset(_fillPaint);
+ SKPaintCache.ReturnReset(_boxShadowPaint);
+
if (_grContext != null)
{
Monitor.Exit(_grContext);
@@ -620,26 +621,33 @@ namespace Avalonia.Skia
public void PushOpacityMask(IBrush mask, Rect bounds)
{
CheckLease();
- // TODO: This should be disposed
- var paint = new SKPaint();
+
+ var paint = SKPaintCache.Get();
Canvas.SaveLayer(paint);
- _maskStack.Push(CreatePaint(paint, mask, bounds.Size, true));
+ _maskStack.Push(CreatePaint(paint, mask, bounds.Size));
}
///
public void PopOpacityMask()
{
CheckLease();
- using (var paint = new SKPaint { BlendMode = SKBlendMode.DstIn })
+
+ var paint = SKPaintCache.Get();
+ paint.BlendMode = SKBlendMode.DstIn;
+
+ Canvas.SaveLayer(paint);
+ SKPaintCache.ReturnReset(paint);
+
+ PaintWrapper paintWrapper;
+ using (paintWrapper = _maskStack.Pop())
{
- Canvas.SaveLayer(paint);
- using (var paintWrapper = _maskStack.Pop())
- {
- Canvas.DrawPaint(paintWrapper.Paint);
- }
- Canvas.Restore();
+ Canvas.DrawPaint(paintWrapper.Paint);
}
+ // Return the paint wrapper's paint less the reset since the paint is already reset in the Dispose method above.
+ SKPaintCache.Return(paintWrapper.Paint);
+
+ Canvas.Restore();
Canvas.Restore();
}
@@ -974,9 +982,9 @@ namespace Avalonia.Skia
);
}
- internal PaintWrapper CreateAcrylicPaint (SKPaint paint, IExperimentalAcrylicMaterial material, bool disposePaint = false)
+ internal PaintWrapper CreateAcrylicPaint (SKPaint paint, IExperimentalAcrylicMaterial material)
{
- var paintWrapper = new PaintWrapper(paint, disposePaint);
+ var paintWrapper = new PaintWrapper(paint);
paint.IsAntialias = true;
@@ -1023,11 +1031,10 @@ namespace Avalonia.Skia
/// The paint to wrap.
/// Source brush.
/// Target size.
- /// Optional dispose of the supplied paint.
/// Paint wrapper for given brush.
- internal PaintWrapper CreatePaint(SKPaint paint, IBrush brush, Size targetSize, bool disposePaint = false)
+ internal PaintWrapper CreatePaint(SKPaint paint, IBrush brush, Size targetSize)
{
- var paintWrapper = new PaintWrapper(paint, disposePaint);
+ var paintWrapper = new PaintWrapper(paint);
paint.IsAntialias = true;
@@ -1080,9 +1087,8 @@ namespace Avalonia.Skia
/// The paint to wrap.
/// Source pen.
/// Target size.
- /// Optional dispose of the supplied paint.
///
- private PaintWrapper CreatePaint(SKPaint paint, IPen pen, Size targetSize, bool disposePaint = false)
+ private PaintWrapper CreatePaint(SKPaint paint, IPen pen, Size targetSize)
{
// In Skia 0 thickness means - use hairline rendering
// and for us it means - there is nothing rendered.
@@ -1091,7 +1097,7 @@ namespace Avalonia.Skia
return default;
}
- var rv = CreatePaint(paint, pen.Brush, targetSize, disposePaint);
+ var rv = CreatePaint(paint, pen.Brush, targetSize);
paint.IsStroke = true;
paint.StrokeWidth = (float) pen.Thickness;
@@ -1206,16 +1212,14 @@ namespace Avalonia.Skia
{
//We are saving memory allocations there
public readonly SKPaint Paint;
- private readonly bool _disposePaint;
private IDisposable _disposable1;
private IDisposable _disposable2;
private IDisposable _disposable3;
- public PaintWrapper(SKPaint paint, bool disposePaint)
+ public PaintWrapper(SKPaint paint)
{
Paint = paint;
- _disposePaint = disposePaint;
_disposable1 = null;
_disposable2 = null;
@@ -1263,15 +1267,7 @@ namespace Avalonia.Skia
///
public void Dispose()
{
- if (_disposePaint)
- {
- Paint?.Dispose();
- }
- else
- {
- Paint?.Reset();
- }
-
+ Paint?.Reset();
_disposable1?.Dispose();
_disposable2?.Dispose();
_disposable3?.Dispose();
diff --git a/src/Skia/Avalonia.Skia/FontManagerImpl.cs b/src/Skia/Avalonia.Skia/FontManagerImpl.cs
index 125dd0e455..90ff9652d8 100644
--- a/src/Skia/Avalonia.Skia/FontManagerImpl.cs
+++ b/src/Skia/Avalonia.Skia/FontManagerImpl.cs
@@ -102,7 +102,7 @@ namespace Avalonia.Skia
return false;
}
- public IGlyphTypefaceImpl CreateGlyphTypeface(Typeface typeface)
+ public IGlyphTypeface CreateGlyphTypeface(Typeface typeface)
{
SKTypeface skTypeface = null;
@@ -148,11 +148,19 @@ namespace Avalonia.Skia
$"Could not create glyph typeface for: {typeface.FontFamily.Name}.");
}
- var isFakeBold = (int)typeface.Weight >= 600 && !skTypeface.IsBold;
+ var fontSimulations = FontSimulations.None;
- var isFakeItalic = typeface.Style == FontStyle.Italic && !skTypeface.IsItalic;
-
- return new GlyphTypefaceImpl(skTypeface, isFakeBold, isFakeItalic);
+ if((int)typeface.Weight >= 600 && !skTypeface.IsBold)
+ {
+ fontSimulations |= FontSimulations.Bold;
+ }
+
+ if(typeface.Style == FontStyle.Italic && !skTypeface.IsItalic)
+ {
+ fontSimulations |= FontSimulations.Oblique;
+ }
+
+ return new GlyphTypefaceImpl(skTypeface, fontSimulations);
}
}
}
diff --git a/src/Skia/Avalonia.Skia/GeometryImpl.cs b/src/Skia/Avalonia.Skia/GeometryImpl.cs
index 19dbcf9713..4037cc4a35 100644
--- a/src/Skia/Avalonia.Skia/GeometryImpl.cs
+++ b/src/Skia/Avalonia.Skia/GeometryImpl.cs
@@ -81,15 +81,14 @@ namespace Avalonia.Skia
}
else
{
- using (var paint = new SKPaint())
- {
- paint.IsStroke = true;
- paint.StrokeWidth = strokeWidth;
+ var paint = SKPaintCache.Get();
+ paint.IsStroke = true;
+ paint.StrokeWidth = strokeWidth;
+ paint.GetFillPath(EffectivePath, strokePath);
- paint.GetFillPath(EffectivePath, strokePath);
+ SKPaintCache.ReturnReset(paint);
- _pathCache.Cache(strokePath, strokeWidth, strokePath.TightBounds.ToAvaloniaRect());
- }
+ _pathCache.Cache(strokePath, strokeWidth, strokePath.TightBounds.ToAvaloniaRect());
}
}
diff --git a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
index dcb4eac7ca..71bdc1bd6b 100644
--- a/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
+++ b/src/Skia/Avalonia.Skia/GlyphTypefaceImpl.cs
@@ -1,18 +1,18 @@
using System;
using System.Runtime.InteropServices;
+using Avalonia.Media;
using Avalonia.Metadata;
-using Avalonia.Platform;
using HarfBuzzSharp;
using SkiaSharp;
namespace Avalonia.Skia
{
[Unstable]
- public class GlyphTypefaceImpl : IGlyphTypefaceImpl
+ public class GlyphTypefaceImpl : IGlyphTypeface
{
private bool _isDisposed;
- public GlyphTypefaceImpl(SKTypeface typeface, bool isFakeBold = false, bool isFakeItalic = false)
+ public GlyphTypefaceImpl(SKTypeface typeface, FontSimulations fontSimulations)
{
Typeface = typeface ?? throw new ArgumentNullException(nameof(typeface));
@@ -25,39 +25,34 @@ namespace Avalonia.Skia
Font.SetFunctionsOpenType();
- DesignEmHeight = (short)Typeface.UnitsPerEm;
-
var metrics = Typeface.ToFont().Metrics;
const double defaultFontRenderingEmSize = 12.0;
- Ascent = (int)(metrics.Ascent / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
-
- Descent = (int)(metrics.Descent / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
-
- LineGap = (int)(metrics.Leading / defaultFontRenderingEmSize * Typeface.UnitsPerEm);
-
- UnderlinePosition = metrics.UnderlinePosition != null ?
+ Metrics = new FontMetrics
+ {
+ DesignEmHeight = (short)Typeface.UnitsPerEm,
+ Ascent = (int)(metrics.Ascent / defaultFontRenderingEmSize * Typeface.UnitsPerEm),
+ Descent = (int)(metrics.Descent / defaultFontRenderingEmSize * Typeface.UnitsPerEm),
+ LineGap = (int)(metrics.Leading / defaultFontRenderingEmSize * Typeface.UnitsPerEm),
+ UnderlinePosition = metrics.UnderlinePosition != null ?
(int)(metrics.UnderlinePosition / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
- 0;
-
- UnderlineThickness = metrics.UnderlineThickness != null ?
+ 0,
+ UnderlineThickness = metrics.UnderlineThickness != null ?
(int)(metrics.UnderlineThickness / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
- 0;
-
- StrikethroughPosition = metrics.StrikeoutPosition != null ?
+ 0,
+ StrikethroughPosition = metrics.StrikeoutPosition != null ?
(int)(metrics.StrikeoutPosition / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
- 0;
-
- StrikethroughThickness = metrics.StrikeoutThickness != null ?
+ 0,
+ StrikethroughThickness = metrics.StrikeoutThickness != null ?
(int)(metrics.StrikeoutThickness / defaultFontRenderingEmSize * Typeface.UnitsPerEm) :
- 0;
-
- IsFixedPitch = Typeface.IsFixedPitch;
+ 0,
+ IsFixedPitch = Typeface.IsFixedPitch
+ };
- IsFakeBold = isFakeBold;
+ GlyphCount = Typeface.GlyphCount;
- IsFakeItalic = isFakeItalic;
+ FontSimulations = fontSimulations;
}
public Face Face { get; }
@@ -66,40 +61,35 @@ namespace Avalonia.Skia
public SKTypeface Typeface { get; }
- public int ReplacementCodepoint { get; }
-
- ///
- public short DesignEmHeight { get; }
-
- ///
- public int Ascent { get; }
-
- ///
- public int Descent { get; }
-
- ///
- public int LineGap { get; }
+ public FontSimulations FontSimulations { get; }
- ///
- public int UnderlinePosition { get; }
+ public int ReplacementCodepoint { get; }
- ///
- public int UnderlineThickness { get; }
+ public FontMetrics Metrics { get; }
- ///
- public int StrikethroughPosition { get; }
+ public int GlyphCount { get; }
- ///
- public int StrikethroughThickness { get; }
+ public bool TryGetGlyphMetrics(ushort glyph, out GlyphMetrics metrics)
+ {
+ metrics = default;
- ///
- public bool IsFixedPitch { get; }
-
- public bool IsFakeBold { get; }
-
- public bool IsFakeItalic { get; }
+ if (!Font.TryGetGlyphExtents(glyph, out var extents))
+ {
+ return false;
+ }
+
+ metrics = new GlyphMetrics
+ {
+ XBearing = extents.XBearing,
+ YBearing = extents.YBearing,
+ Width = extents.Width,
+ Height = extents.Height
+ };
+
+ return true;
+ }
- ///
+ ///
public ushort GetGlyph(uint codepoint)
{
if (Font.TryGetGlyph(codepoint, out var glyph))
@@ -110,7 +100,14 @@ namespace Avalonia.Skia
return 0;
}
- ///
+ public bool TryGetGlyph(uint codepoint, out ushort glyph)
+ {
+ glyph = GetGlyph(codepoint);
+
+ return glyph != 0;
+ }
+
+ ///
public ushort[] GetGlyphs(ReadOnlySpan codepoints)
{
var glyphs = new ushort[codepoints.Length];
@@ -126,13 +123,13 @@ namespace Avalonia.Skia
return glyphs;
}
- ///
+ ///
public int GetGlyphAdvance(ushort glyph)
{
return Font.GetHorizontalGlyphAdvance(glyph);
}
- ///
+ ///
public int[] GetGlyphAdvances(ReadOnlySpan glyphs)
{
var glyphIndices = new uint[glyphs.Length];
@@ -180,5 +177,10 @@ namespace Avalonia.Skia
Dispose(true);
GC.SuppressFinalize(this);
}
+
+ public bool TryGetTable(uint tag, out byte[] table)
+ {
+ return Typeface.TryGetTableData(tag, out table);
+ }
}
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs
index d700d4848e..857433f95f 100644
--- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/OpenGlBitmapImpl.cs
@@ -25,9 +25,9 @@ namespace Avalonia.Skia
public Vector Dpi { get; }
public PixelSize PixelSize { get; }
public int Version { get; private set; }
- public void Save(string fileName) => throw new NotSupportedException();
+ public void Save(string fileName, int? quality = null) => throw new NotSupportedException();
- public void Save(Stream stream) => throw new NotSupportedException();
+ public void Save(Stream stream, int? quality = null) => throw new NotSupportedException();
public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
{
diff --git a/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs b/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs
index 5fa961cc99..b4dd754822 100644
--- a/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs
+++ b/src/Skia/Avalonia.Skia/Helpers/ImageSavingHelper.cs
@@ -14,14 +14,19 @@ namespace Avalonia.Skia.Helpers
///
/// Image to save
/// Target file.
- public static void SaveImage(SKImage image, string fileName)
+ ///
+ /// The optional quality for PNG compression.
+ /// The quality value is interpreted from 0 - 100. If quality is null
+ /// the encoder applies the default quality value.
+ ///
+ public static void SaveImage(SKImage image, string fileName, int? quality = null)
{
if (image == null) throw new ArgumentNullException(nameof(image));
if (fileName == null) throw new ArgumentNullException(nameof(fileName));
using (var stream = File.Create(fileName))
{
- SaveImage(image, stream);
+ SaveImage(image, stream, quality);
}
}
@@ -29,16 +34,30 @@ namespace Avalonia.Skia.Helpers
/// Save Skia image to a stream.
///
/// Image to save
- /// Target stream.
- public static void SaveImage(SKImage image, Stream stream)
+ ///
+ /// The optional quality for PNG compression.
+ /// The quality value is interpreted from 0 - 100. If quality is null
+ /// the encoder applies the default quality value.
+ ///
+ public static void SaveImage(SKImage image, Stream stream, int? quality = null)
{
if (image == null) throw new ArgumentNullException(nameof(image));
if (stream == null) throw new ArgumentNullException(nameof(stream));
- using (var data = image.Encode())
+ if (quality == null)
{
- data.SaveTo(stream);
+ using (var data = image.Encode())
+ {
+ data.SaveTo(stream);
+ }
+ }
+ else
+ {
+ using (var data = image.Encode(SKEncodedImageFormat.Png, (int)quality))
+ {
+ data.SaveTo(stream);
+ }
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs
index 6400d67fde..e24d805050 100644
--- a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs
+++ b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs
@@ -139,13 +139,13 @@ namespace Avalonia.Skia
}
///
- public void Save(string fileName)
+ public void Save(string fileName, int? quality = null)
{
ImageSavingHelper.SaveImage(_image, fileName);
}
///
- public void Save(Stream stream)
+ public void Save(Stream stream, int? quality = null)
{
ImageSavingHelper.SaveImage(_image, stream);
}
diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
index 91fe4fc085..f34e25299c 100644
--- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
+++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.IO;
+using System.IO;
using System.Linq;
using System.Threading;
@@ -33,13 +33,17 @@ namespace Avalonia.Skia
}
var gl = AvaloniaLocator.Current.GetService();
- if (gl != null)
+ if (gl != null)
_skiaGpu = new GlSkiaGpu(gl, maxResourceBytes);
-
- //TODO: SKFont crashes when disposed in finalizer so we keep it alive
- GC.SuppressFinalize(s_font);
}
+
+ public bool SupportsIndividualRoundRects => true;
+
+ public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul;
+
+ public PixelFormat DefaultPixelFormat { get; }
+
public IGeometryImpl CreateEllipseGeometry(Rect rect) => new EllipseGeometryImpl(rect);
public IGeometryImpl CreateLineGeometry(Point p1, Point p2) => new LineGeometryImpl(p1, p2);
@@ -64,7 +68,7 @@ namespace Avalonia.Skia
public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun)
{
- if (glyphRun.GlyphTypeface.PlatformImpl is not GlyphTypefaceImpl glyphTypeface)
+ if (glyphRun.GlyphTypeface is not GlyphTypefaceImpl glyphTypeface)
{
throw new InvalidOperationException("PlatformImpl can't be null.");
}
@@ -73,7 +77,7 @@ namespace Avalonia.Skia
var skFont = new SKFont(glyphTypeface.Typeface, fontRenderingEmSize)
{
Size = fontRenderingEmSize,
- Edging = SKFontEdging.Antialias,
+ Edging = SKFontEdging.Alias,
Hinting = SKFontHinting.None,
LinearMetrics = true
};
@@ -228,133 +232,101 @@ namespace Avalonia.Skia
return new WriteableBitmapImpl(size, dpi, format, alphaFormat);
}
- private static readonly SKFont s_font = new SKFont
+ public IOpenGlBitmapImpl CreateOpenGlBitmap(PixelSize size, Vector dpi)
{
- Subpixel = true,
- Edging = SKFontEdging.SubpixelAntialias,
- Hinting = SKFontHinting.Full,
- LinearMetrics = true
- };
-
- private static readonly ThreadLocal s_textBlobBuilderThreadLocal = new ThreadLocal(() => new SKTextBlobBuilder());
+ if (_skiaGpu is IOpenGlAwareSkiaGpu glAware)
+ return glAware.CreateOpenGlBitmap(size, dpi);
+ if (_skiaGpu == null)
+ throw new PlatformNotSupportedException("GPU acceleration is not available");
+ throw new PlatformNotSupportedException(
+ "Current GPU acceleration backend does not support OpenGL integration");
+ }
- ///
- public IGlyphRunImpl CreateGlyphRun(GlyphRun glyphRun)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphIndices,
+ IReadOnlyList glyphAdvances, IReadOnlyList glyphOffsets)
{
- var count = glyphRun.GlyphIndices.Count;
- var textBlobBuilder = s_textBlobBuilderThreadLocal.Value;
+ if (glyphTypeface == null)
+ {
+ throw new ArgumentNullException(nameof(glyphTypeface));
+ }
- var glyphTypeface = (GlyphTypefaceImpl)glyphRun.GlyphTypeface.PlatformImpl;
+ if (glyphIndices == null)
+ {
+ throw new ArgumentNullException(nameof(glyphIndices));
+ }
- var typeface = glyphTypeface.Typeface;
+ var glyphTypefaceImpl = glyphTypeface as GlyphTypefaceImpl;
- s_font.Size = (float)glyphRun.FontRenderingEmSize;
- s_font.Typeface = typeface;
- s_font.Embolden = glyphTypeface.IsFakeBold;
- s_font.SkewX = glyphTypeface.IsFakeItalic ? -0.2f : 0;
+ var font = new SKFont
+ {
+ LinearMetrics = true,
+ Subpixel = true,
+ Edging = SKFontEdging.SubpixelAntialias,
+ Hinting = SKFontHinting.Full,
+ Size = (float)fontRenderingEmSize,
+ Typeface = glyphTypefaceImpl.Typeface,
+ Embolden = (glyphTypefaceImpl.FontSimulations & FontSimulations.Bold) != 0,
+ SkewX = (glyphTypefaceImpl.FontSimulations & FontSimulations.Oblique) != 0 ? -0.2f : 0
+ };
- SKTextBlob textBlob;
+ var builder = new SKTextBlobBuilder();
- var scale = (float)(glyphRun.FontRenderingEmSize / glyphTypeface.DesignEmHeight);
+ var count = glyphIndices.Count;
- if (glyphRun.GlyphOffsets == null)
+ if (glyphOffsets != null && glyphAdvances != null)
{
- if (glyphTypeface.IsFixedPitch)
- {
- var buffer = textBlobBuilder.AllocateRun(s_font, glyphRun.GlyphIndices.Count, 0, 0);
+ var runBuffer = builder.AllocatePositionedRun(font, count);
- var glyphs = buffer.GetGlyphSpan();
+ var glyphSpan = runBuffer.GetGlyphSpan();
+ var positionSpan = runBuffer.GetPositionSpan();
- for (int i = 0; i < glyphs.Length; i++)
- {
- glyphs[i] = glyphRun.GlyphIndices[i];
- }
+ var currentX = 0.0;
- textBlob = textBlobBuilder.Build();
- }
- else
+ for (int i = 0; i < glyphOffsets.Count; i++)
{
- var buffer = textBlobBuilder.AllocateHorizontalRun(s_font, count, 0);
-
- var positions = buffer.GetPositionSpan();
-
- var width = 0d;
-
- for (var i = 0; i < count; i++)
- {
- positions[i] = (float)width;
-
- if (glyphRun.GlyphAdvances == null)
- {
- width += glyphTypeface.GetGlyphAdvance(glyphRun.GlyphIndices[i]) * scale;
- }
- else
- {
- width += glyphRun.GlyphAdvances[i];
- }
- }
+ var offset = glyphOffsets[i];
- var glyphs = buffer.GetGlyphSpan();
+ glyphSpan[i] = glyphIndices[i];
- for (int i = 0; i < glyphs.Length; i++)
- {
- glyphs[i] = glyphRun.GlyphIndices[i];
- }
+ positionSpan[i] = new SKPoint((float)(currentX + offset.X), (float)offset.Y);
- textBlob = textBlobBuilder.Build();
+ currentX += glyphAdvances[i];
}
}
else
{
- var buffer = textBlobBuilder.AllocatePositionedRun(s_font, count);
+ if (glyphAdvances != null)
+ {
+ var runBuffer = builder.AllocateHorizontalRun(font, count, 0);
- var glyphPositions = buffer.GetPositionSpan();
+ var glyphSpan = runBuffer.GetGlyphSpan();
+ var positionSpan = runBuffer.GetPositionSpan();
- var currentX = 0.0;
+ var currentX = 0.0;
- for (var i = 0; i < count; i++)
- {
- var glyphOffset = glyphRun.GlyphOffsets[i];
+ for (int i = 0; i < glyphAdvances.Count; i++)
+ {
+ glyphSpan[i] = glyphIndices[i];
- glyphPositions[i] = new SKPoint((float)(currentX + glyphOffset.X), (float)glyphOffset.Y);
+ positionSpan[i] = (float)currentX;
- if (glyphRun.GlyphAdvances == null)
- {
- currentX += glyphTypeface.GetGlyphAdvance(glyphRun.GlyphIndices[i]) * scale;
- }
- else
- {
- currentX += glyphRun.GlyphAdvances[i];
+ currentX += glyphAdvances[i];
}
}
+ else
+ {
+ var runBuffer = builder.AllocateRun(font, count, 0, 0);
- var glyphs = buffer.GetGlyphSpan();
+ var glyphSpan = runBuffer.GetGlyphSpan();
- for (int i = 0; i < glyphs.Length; i++)
- {
- glyphs[i] = glyphRun.GlyphIndices[i];
+ for (int i = 0; i < glyphIndices.Count; i++)
+ {
+ glyphSpan[i] = glyphIndices[i];
+ }
}
-
- textBlob = textBlobBuilder.Build();
}
- return new GlyphRunImpl(textBlob);
+ return new GlyphRunImpl(builder.Build());
}
-
- public IOpenGlBitmapImpl CreateOpenGlBitmap(PixelSize size, Vector dpi)
- {
- if (_skiaGpu is IOpenGlAwareSkiaGpu glAware)
- return glAware.CreateOpenGlBitmap(size, dpi);
- if (_skiaGpu == null)
- throw new PlatformNotSupportedException("GPU acceleration is not available");
- throw new PlatformNotSupportedException(
- "Current GPU acceleration backend does not support OpenGL integration");
- }
-
- public bool SupportsIndividualRoundRects => true;
-
- public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul;
-
- public PixelFormat DefaultPixelFormat { get; }
}
}
diff --git a/src/Skia/Avalonia.Skia/SKPaintCache.cs b/src/Skia/Avalonia.Skia/SKPaintCache.cs
new file mode 100644
index 0000000000..6588ab8da8
--- /dev/null
+++ b/src/Skia/Avalonia.Skia/SKPaintCache.cs
@@ -0,0 +1,76 @@
+using System.Collections.Concurrent;
+using SkiaSharp;
+
+namespace Avalonia.Skia
+{
+ ///
+ /// Cache for SKPaints.
+ ///
+ internal static class SKPaintCache
+ {
+ private static ConcurrentBag s_cachedPaints;
+
+ static SKPaintCache()
+ {
+ s_cachedPaints = new ConcurrentBag();
+ }
+
+ ///
+ /// Gets a SKPaint for usage.
+ ///
+ ///
+ /// If a SKPaint is in the cache, that existing SKPaint will be returned.
+ /// Otherwise a new SKPaint will be created.
+ ///
+ ///
+ public static SKPaint Get()
+ {
+ if (!s_cachedPaints.TryTake(out var paint))
+ {
+ paint = new SKPaint();
+ }
+
+ return paint;
+ }
+
+ ///
+ /// Returns a SKPaint for reuse later.
+ ///
+ ///
+ /// Do not use the paint further.
+ /// Do not return the same paint multiple times as that will break the cache.
+ ///
+ ///
+ public static void Return(SKPaint paint)
+ {
+ s_cachedPaints.Add(paint);
+ }
+
+ ///
+ /// Returns a SKPaint and resets it for reuse later.
+ ///
+ ///
+ /// Do not use the paint further.
+ /// Do not return the same paint multiple times as that will break the cache.
+ /// Uses SKPaint.Reset() for reuse later.
+ ///
+ ///
+ public static void ReturnReset(SKPaint paint)
+ {
+ paint.Reset();
+ s_cachedPaints.Add(paint);
+ }
+
+ ///
+ /// Clears and disposes all cached paints.
+ ///
+ public static void Clear()
+ {
+ while (s_cachedPaints.TryTake(out var paint))
+ {
+ paint.Dispose();
+ }
+ }
+
+ }
+}
diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
index 01b7449b64..d3231c92a5 100644
--- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
@@ -116,20 +116,20 @@ namespace Avalonia.Skia
public int Version { get; private set; } = 1;
///
- public void Save(string fileName)
+ public void Save(string fileName, int? quality = null)
{
using (var image = SnapshotImage())
{
- ImageSavingHelper.SaveImage(image, fileName);
+ ImageSavingHelper.SaveImage(image, fileName, quality);
}
}
///
- public void Save(Stream stream)
+ public void Save(Stream stream, int? quality = null)
{
using (var image = SnapshotImage())
{
- ImageSavingHelper.SaveImage(image, stream);
+ ImageSavingHelper.SaveImage(image, stream, quality);
}
}
diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
index 6da8a20f6a..eaf588c27d 100644
--- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs
+++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Skia
buffer.Language = new Language(culture ?? CultureInfo.CurrentCulture);
- var font = ((GlyphTypefaceImpl)typeface.PlatformImpl).Font;
+ var font = ((GlyphTypefaceImpl)typeface).Font;
font.Shape(buffer);
@@ -60,11 +60,11 @@ namespace Avalonia.Skia
var glyphCluster = (int)(sourceInfo.Cluster);
- var glyphAdvance = GetGlyphAdvance(glyphPositions, i, textScale);
+ var glyphAdvance = GetGlyphAdvance(glyphPositions, i, textScale) + options.LetterSpacing;
var glyphOffset = GetGlyphOffset(glyphPositions, i, textScale);
- if(glyphIndex == 0 && text.Buffer.Span[glyphCluster] == '\t')
+ if(text.Buffer.Span[glyphCluster] == '\t')
{
glyphIndex = typeface.GetGlyph(' ');
diff --git a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
index 80bfcc5973..d437f514bb 100644
--- a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
+++ b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
@@ -137,20 +137,20 @@ namespace Avalonia.Skia
}
///
- public void Save(Stream stream)
+ public void Save(Stream stream, int? quality = null)
{
using (var image = GetSnapshot())
{
- ImageSavingHelper.SaveImage(image, stream);
+ ImageSavingHelper.SaveImage(image, stream, quality);
}
}
///
- public void Save(string fileName)
+ public void Save(string fileName, int? quality = null)
{
using (var image = GetSnapshot())
{
- ImageSavingHelper.SaveImage(image, fileName);
+ ImageSavingHelper.SaveImage(image, fileName, quality);
}
}
diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.CompilationTuning.props b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.CompilationTuning.props
deleted file mode 100644
index eb5e5dd733..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.CompilationTuning.props
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- 16777216
- false
- false
-
-
diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj
deleted file mode 100644
index 693a6a1462..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
- net6.0
- enable
- Avalonia.Web.Blazor
- preview
- false
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- build\
-
-
- true
- build\;buildTransitive\
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.props b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.props
deleted file mode 100644
index dd96a60c6a..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.props
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.targets b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.targets
deleted file mode 100644
index e9052fda88..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.targets
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs b/src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs
deleted file mode 100644
index 11d9bcc98f..0000000000
--- a/src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Platform;
-
-namespace Avalonia.Web.Blazor
-{
- public class AvaloniaBlazorAppBuilder : AppBuilderBase
- {
- public AvaloniaBlazorAppBuilder(IRuntimePlatform platform, Action platformServices)
- : base(platform, platformServices)
- {
- }
-
- public AvaloniaBlazorAppBuilder()
- : base(new StandardRuntimePlatform(),
- builder => StandardRuntimePlatformServices.Register(builder.ApplicationType!.Assembly))
- {
- UseWindowingSubsystem(BlazorWindowingPlatform.Register);
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor b/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor
deleted file mode 100644
index 5a3b9d5f71..0000000000
--- a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
diff --git a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs b/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
deleted file mode 100644
index 0e64e98f1e..0000000000
--- a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
+++ /dev/null
@@ -1,500 +0,0 @@
-using System.Diagnostics;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Controls.Embedding;
-using Avalonia.Controls.Platform;
-using Avalonia.Input;
-using Avalonia.Input.Raw;
-using Avalonia.Input.TextInput;
-using Avalonia.Platform.Storage;
-using Avalonia.Rendering;
-using Avalonia.Rendering.Composition;
-using Avalonia.Web.Blazor.Interop;
-using Avalonia.Web.Blazor.Interop.Storage;
-
-using Microsoft.AspNetCore.Components;
-using Microsoft.AspNetCore.Components.Forms;
-using Microsoft.AspNetCore.Components.Web;
-using Microsoft.JSInterop;
-
-using SkiaSharp;
-using HTMLPointerEventArgs = Microsoft.AspNetCore.Components.Web.PointerEventArgs;
-
-namespace Avalonia.Web.Blazor
-{
- public partial class AvaloniaView : ITextInputMethodImpl
- {
- private readonly RazorViewTopLevelImpl _topLevelImpl;
- private EmbeddableControlRoot _topLevel;
-
- // Interop
- private SKHtmlCanvasInterop? _interop = null;
- private SizeWatcherInterop? _sizeWatcher = null;
- private DpiWatcherInterop? _dpiWatcher = null;
- private SKHtmlCanvasInterop.GLInfo? _jsGlInfo = null;
- private AvaloniaModule? _avaloniaModule = null;
- private InputHelperInterop? _inputHelper = null;
- private FocusHelperInterop? _canvasHelper = null;
- private FocusHelperInterop? _containerHelper = null;
- private NativeControlHostInterop? _nativeControlHost = null;
- private StorageProviderInterop? _storageProvider = null;
- private ElementReference _htmlCanvas;
- private ElementReference _inputElement;
- private ElementReference _containerElement;
- private ElementReference _nativeControlsContainer;
- private double _dpi = 1;
- private SKSize _canvasSize = new (100, 100);
-
- private GRContext? _context;
- private GRGlInterface? _glInterface;
- private const SKColorType ColorType = SKColorType.Rgba8888;
-
- private bool _useGL;
- private bool _inputElementFocused;
-
- private ITextInputMethodClient? _client;
-
-
- [Inject] private IJSRuntime Js { get; set; } = null!;
-
- public AvaloniaView()
- {
- _topLevelImpl = new RazorViewTopLevelImpl(this);
-
- _topLevel = new EmbeddableControlRoot(_topLevelImpl);
-
- if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
- {
- _topLevel.Content = lifetime.MainView;
- }
- }
-
- public bool KeyPreventDefault { get; set; }
-
- public ITextInputMethodClient? Client => _client;
-
- public bool IsActive => _client != null;
-
- public bool IsComposing { get; private set; }
-
- internal INativeControlHostImpl GetNativeControlHostImpl()
- {
- return _nativeControlHost ?? throw new InvalidOperationException("Blazor View wasn't initialized yet");
- }
-
- internal IStorageProvider GetStorageProvider()
- {
- return _storageProvider ?? throw new InvalidOperationException("Blazor View wasn't initialized yet");
- }
-
- private void OnPointerCancel(HTMLPointerEventArgs e)
- {
- if (e.PointerType == "touch")
- {
- _topLevelImpl.RawPointerEvent(RawPointerEventType.TouchCancel, e.PointerType, GetPointFromEventArgs(e),
- GetModifiers(e), e.PointerId);
- }
- }
-
- private void OnPointerMove(HTMLPointerEventArgs e)
- {
- var type = e.PointerType switch
- {
- "touch" => RawPointerEventType.TouchUpdate,
- _ => RawPointerEventType.Move
- };
-
- _topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
- }
-
- private void OnPointerUp(HTMLPointerEventArgs e)
- {
- var type = e.PointerType switch
- {
- "touch" => RawPointerEventType.TouchEnd,
- _ => e.Button switch
- {
- 0 => RawPointerEventType.LeftButtonUp,
- 1 => RawPointerEventType.MiddleButtonUp,
- 2 => RawPointerEventType.RightButtonUp,
- 3 => RawPointerEventType.XButton1Up,
- 4 => RawPointerEventType.XButton2Up,
- // 5 => Pen eraser button,
- _ => RawPointerEventType.Move
- }
- };
-
- _topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
- }
-
- private void OnPointerDown(HTMLPointerEventArgs e)
- {
- var type = e.PointerType switch
- {
- "touch" => RawPointerEventType.TouchBegin,
- _ => e.Button switch
- {
- 0 => RawPointerEventType.LeftButtonDown,
- 1 => RawPointerEventType.MiddleButtonDown,
- 2 => RawPointerEventType.RightButtonDown,
- 3 => RawPointerEventType.XButton1Down,
- 4 => RawPointerEventType.XButton2Down,
- // 5 => Pen eraser button,
- _ => RawPointerEventType.Move
- }
- };
-
- _topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
- }
-
- private static RawPointerPoint GetPointFromEventArgs(HTMLPointerEventArgs args)
- {
- return new RawPointerPoint
- {
- Position = new Point(args.ClientX, args.ClientY),
- Pressure = args.Pressure,
- XTilt = args.TiltX,
- YTilt = args.TiltY
- // Twist = args.Twist - read from JS code directly when
- };
- }
-
- private void OnWheel(WheelEventArgs e)
- {
- _topLevelImpl.RawMouseWheelEvent( new Point(e.ClientX, e.ClientY),
- new Vector(-(e.DeltaX / 50), -(e.DeltaY / 50)), GetModifiers(e));
- }
-
- private static RawInputModifiers GetModifiers(MouseEventArgs e)
- {
- var modifiers = RawInputModifiers.None;
-
- if (e.CtrlKey)
- modifiers |= RawInputModifiers.Control;
- if (e.AltKey)
- modifiers |= RawInputModifiers.Alt;
- if (e.ShiftKey)
- modifiers |= RawInputModifiers.Shift;
- if (e.MetaKey)
- modifiers |= RawInputModifiers.Meta;
-
- if ((e.Buttons & 1L) == 1)
- modifiers |= RawInputModifiers.LeftMouseButton;
-
- if ((e.Buttons & 2L) == 2)
- modifiers |= e.Type == "pen" ? RawInputModifiers.PenBarrelButton : RawInputModifiers.RightMouseButton;
-
- if ((e.Buttons & 4L) == 4)
- modifiers |= RawInputModifiers.MiddleMouseButton;
-
- if ((e.Buttons & 8L) == 8)
- modifiers |= RawInputModifiers.XButton1MouseButton;
-
- if ((e.Buttons & 16L) == 16)
- modifiers |= RawInputModifiers.XButton2MouseButton;
-
- if ((e.Buttons & 32L) == 32)
- modifiers |= RawInputModifiers.PenEraser;
-
- return modifiers;
- }
-
- private static RawInputModifiers GetModifiers(KeyboardEventArgs e)
- {
- var modifiers = RawInputModifiers.None;
-
- if (e.CtrlKey)
- modifiers |= RawInputModifiers.Control;
- if (e.AltKey)
- modifiers |= RawInputModifiers.Alt;
- if (e.ShiftKey)
- modifiers |= RawInputModifiers.Shift;
- if (e.MetaKey)
- modifiers |= RawInputModifiers.Meta;
-
- return modifiers;
- }
-
- private void OnKeyDown(KeyboardEventArgs e)
- {
- KeyPreventDefault = _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyDown, e.Code, e.Key, GetModifiers(e));
- }
-
- private void OnKeyUp(KeyboardEventArgs e)
- {
- KeyPreventDefault = _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyUp, e.Code, e.Key, GetModifiers(e));
- }
-
- private void OnFocus(FocusEventArgs e)
- {
- // if focus has unexpectedly moved from the input element to the container element,
- // shift it back to the input element
- if (_inputElementFocused && _inputHelper is not null)
- {
- _inputHelper.Focus();
- }
- }
-
- [Parameter(CaptureUnmatchedValues = true)]
- public IReadOnlyDictionary? AdditionalAttributes { get; set; }
-
- protected override async Task OnAfterRenderAsync(bool firstRender)
- {
- if (firstRender)
- {
- AvaloniaLocator.CurrentMutable.Bind().ToConstant((IJSInProcessRuntime)Js);
-
- _avaloniaModule = await AvaloniaModule.ImportAsync(Js);
-
- _canvasHelper = new FocusHelperInterop(_avaloniaModule, _htmlCanvas);
- _containerHelper = new FocusHelperInterop(_avaloniaModule, _containerElement);
- _inputHelper = new InputHelperInterop(_avaloniaModule, _inputElement);
-
- _inputHelper.CompositionEvent += InputHelperOnCompositionEvent;
- _inputHelper.InputEvent += InputHelperOnInputEvent;
-
- HideIme();
- _canvasHelper.SetCursor("default");
- _topLevelImpl.SetCssCursor = x =>
- {
- _inputHelper.SetCursor(x); //macOS
- _canvasHelper.SetCursor(x); //windows
- };
-
- _nativeControlHost = new NativeControlHostInterop(_avaloniaModule, _nativeControlsContainer);
- _storageProvider = await StorageProviderInterop.ImportAsync(Js);
-
- Console.WriteLine("starting html canvas setup");
- _interop = new SKHtmlCanvasInterop(_avaloniaModule, _htmlCanvas, OnRenderFrame);
-
- Console.WriteLine("Interop created");
-
- var skiaOptions = AvaloniaLocator.Current.GetService();
- _useGL = skiaOptions?.CustomGpuFactory != null;
-
- if (_useGL)
- {
- _jsGlInfo = _interop.InitGL();
- Console.WriteLine("jsglinfo created - init gl");
- }
- else
- {
- var rasterInitialized = _interop.InitRaster();
- Console.WriteLine("raster initialized: {0}", rasterInitialized);
- }
-
- if (_useGL)
- {
- // create the SkiaSharp context
- if (_context == null)
- {
- _glInterface = GRGlInterface.Create();
- _context = GRContext.CreateGl(_glInterface);
-
-
- // bump the default resource cache limit
- _context.SetResourceCacheLimit(skiaOptions?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
- Console.WriteLine("glcontext created and resource limit set");
- }
-
- _topLevelImpl.SetSurface(_context, _jsGlInfo!, ColorType,
- new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi);
- }
- else
- {
- _topLevelImpl.SetSurface(ColorType,
- new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi, _interop.PutImageData);
- }
-
- _interop.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
-
- Threading.Dispatcher.UIThread.Post(async () =>
- {
- _interop.RequestAnimationFrame(true);
-
- _sizeWatcher = new SizeWatcherInterop(_avaloniaModule, _htmlCanvas, OnSizeChanged);
- _dpiWatcher = new DpiWatcherInterop(_avaloniaModule, OnDpiChanged);
-
- _sizeWatcher.Start();
- _topLevel.Prepare();
-
- _topLevel.Renderer.Start();
- });
- }
- }
-
- private void InputHelperOnInputEvent(object? sender, WebInputEventArgs e)
- {
- if (IsComposing)
- {
- return;
- }
-
- _topLevelImpl.RawTextEvent(e.Data);
-
- e.Handled = true;
- }
-
- private void InputHelperOnCompositionEvent(object? sender, WebCompositionEventArgs e)
- {
- if(_client == null)
- {
- return;
- }
-
- switch (e.Type)
- {
- case WebCompositionEventArgs.WebCompositionEventType.Start:
- _client.SetPreeditText(null);
- IsComposing = true;
- break;
- case WebCompositionEventArgs.WebCompositionEventType.Update:
- _client.SetPreeditText(e.Data);
- break;
- case WebCompositionEventArgs.WebCompositionEventType.End:
- IsComposing = false;
- _client.SetPreeditText(null);
- _topLevelImpl.RawTextEvent(e.Data);
- break;
- }
- }
-
- private void OnRenderFrame()
- {
- if (_useGL && (_jsGlInfo == null))
- {
- Console.WriteLine("nothing to render");
- return;
- }
- if (_canvasSize.Width <= 0 || _canvasSize.Height <= 0 || _dpi <= 0)
- {
- Console.WriteLine("nothing to render");
- return;
- }
-
- ManualTriggerRenderTimer.Instance.RaiseTick();
- }
-
- public void Dispose()
- {
- _dpiWatcher?.Unsubscribe(OnDpiChanged);
- _sizeWatcher?.Dispose();
- _interop?.Dispose();
- }
-
- private void ForceBlit()
- {
- // Note: this is technically a hack, but it's a kinda unique use case when
- // we want to blit the previous frame
- // renderer doesn't have much control over the render target
- // we render on the UI thread
- // We also don't want to have it as a meaningful public API.
- // Therefore we have InternalsVisibleTo hack here.
-
- if (_topLevel.Renderer is CompositingRenderer dr)
- {
- dr.CompositionTarget.ImmediateUIThreadRender();
- }
- }
-
- private void OnDpiChanged(double newDpi)
- {
- if (Math.Abs(_dpi - newDpi) > 0.0001)
- {
- _dpi = newDpi;
-
- _interop!.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
-
- _topLevelImpl.SetClientSize(_canvasSize, _dpi);
-
- ForceBlit();
- }
- }
-
- private void OnSizeChanged(SKSize newSize)
- {
- if (_canvasSize != newSize)
- {
- _canvasSize = newSize;
-
- _interop!.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
-
- _topLevelImpl.SetClientSize(_canvasSize, _dpi);
-
- ForceBlit();
- }
- }
-
- private void HideIme()
- {
- _inputHelper?.Hide();
- _containerHelper?.Focus();
- }
-
- public void SetClient(ITextInputMethodClient? client)
- {
- if (_inputHelper is null)
- {
- return;
- }
-
- if(_client != null)
- {
- _client.SurroundingTextChanged -= SurroundingTextChanged;
- }
-
- if(client != null)
- {
- client.SurroundingTextChanged += SurroundingTextChanged;
- }
-
- _inputHelper.Clear();
-
- _client = client;
-
- if (IsActive && _client != null)
- {
- _inputHelper.Show();
- _inputElementFocused = true;
- _inputHelper.Focus();
-
- var surroundingText = _client.SurroundingText;
-
- _inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
- }
- else
- {
- _inputElementFocused = false;
- HideIme();
- }
- }
-
- private void SurroundingTextChanged(object? sender, EventArgs e)
- {
- if(_client != null)
- {
- var surroundingText = _client.SurroundingText;
-
- _inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
- }
- }
-
- public void SetCursorRect(Rect rect)
- {
- _inputHelper?.Focus();
- var bounds = new PixelRect((int)rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height);
-
- _inputHelper?.SetBounds(bounds, _client?.SurroundingText.CursorOffset ?? 0);
- _inputHelper?.Focus();
- }
-
- public void SetOptions(TextInputOptions options)
- {
- }
-
- public void Reset()
- {
- _inputHelper?.Clear();
- _inputHelper?.SetSurroundingText("", 0, 0);
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSingleViewLifetime.cs b/src/Web/Avalonia.Web.Blazor/BlazorSingleViewLifetime.cs
deleted file mode 100644
index 7970f09a58..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSingleViewLifetime.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Media;
-
-namespace Avalonia.Web.Blazor
-{
- public class BlazorSingleViewLifetime : ISingleViewApplicationLifetime
- {
- public Control? MainView { get; set; }
- }
-
- public static class WebAppBuilder
- {
- public static T SetupWithSingleViewLifetime(
- this T builder)
- where T : AppBuilderBase, new()
- {
- return builder.SetupWithLifetime(new BlazorSingleViewLifetime());
- }
-
- public static AvaloniaBlazorAppBuilder Configure()
- where TApp : Application, new()
- {
- var builder = AvaloniaBlazorAppBuilder.Configure()
- .UseSkia()
- .With(new SkiaOptions { CustomGpuFactory = () => new BlazorSkiaGpu() });
-
- return builder;
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpu.cs b/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpu.cs
deleted file mode 100644
index 6fa7bf0bde..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpu.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Avalonia.Skia;
-
-namespace Avalonia.Web.Blazor
-{
- public class BlazorSkiaGpu : ISkiaGpu
- {
- public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable surfaces)
- {
- foreach (var surface in surfaces)
- {
- if (surface is BlazorSkiaSurface blazorSkiaSurface)
- {
- return new BlazorSkiaGpuRenderTarget(blazorSkiaSurface);
- }
- }
-
- return null;
- }
-
- public ISkiaSurface? TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session)
- {
- return null;
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderSession.cs b/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderSession.cs
deleted file mode 100644
index 0c53825131..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderSession.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using Avalonia.Skia;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor
-{
- internal class BlazorSkiaGpuRenderSession : ISkiaGpuRenderSession
- {
- private readonly SKSurface _surface;
-
-
- public BlazorSkiaGpuRenderSession(BlazorSkiaSurface blazorSkiaSurface, GRBackendRenderTarget renderTarget)
- {
- _surface = SKSurface.Create(blazorSkiaSurface.Context, renderTarget, blazorSkiaSurface.Origin, blazorSkiaSurface.ColorType);
-
- GrContext = blazorSkiaSurface.Context;
-
- ScaleFactor = blazorSkiaSurface.Scaling;
-
- SurfaceOrigin = blazorSkiaSurface.Origin;
- }
-
- public void Dispose()
- {
- _surface.Flush();
-
- _surface.Dispose();
- }
-
- public GRContext GrContext { get; }
-
- public SKSurface SkSurface => _surface;
-
- public double ScaleFactor { get; }
-
- public GRSurfaceOrigin SurfaceOrigin { get; }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderTarget.cs b/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderTarget.cs
deleted file mode 100644
index fa6a39f210..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderTarget.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Avalonia.Skia;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor
-{
- internal class BlazorSkiaGpuRenderTarget : ISkiaGpuRenderTarget
- {
- private readonly GRBackendRenderTarget _renderTarget;
- private readonly BlazorSkiaSurface _blazorSkiaSurface;
- private readonly PixelSize _size;
-
- public BlazorSkiaGpuRenderTarget(BlazorSkiaSurface blazorSkiaSurface)
- {
- _size = blazorSkiaSurface.Size;
-
- var glFbInfo = new GRGlFramebufferInfo(blazorSkiaSurface.GlInfo.FboId, blazorSkiaSurface.ColorType.ToGlSizedFormat());
- {
- _blazorSkiaSurface = blazorSkiaSurface;
- _renderTarget = new GRBackendRenderTarget(
- (int)(blazorSkiaSurface.Size.Width * blazorSkiaSurface.Scaling),
- (int)(blazorSkiaSurface.Size.Height * blazorSkiaSurface.Scaling),
- blazorSkiaSurface.GlInfo.Samples,
- blazorSkiaSurface.GlInfo.Stencils, glFbInfo);
- }
- }
-
- public void Dispose()
- {
- _renderTarget.Dispose();
- }
-
- public ISkiaGpuRenderSession BeginRenderingSession()
- {
- return new BlazorSkiaGpuRenderSession(_blazorSkiaSurface, _renderTarget);
- }
-
- public bool IsCorrupted => _blazorSkiaSurface.Size != _size;
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSkiaRasterSurface.cs b/src/Web/Avalonia.Web.Blazor/BlazorSkiaRasterSurface.cs
deleted file mode 100644
index 603a792de3..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSkiaRasterSurface.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System.Runtime.InteropServices;
-using Avalonia.Controls.Platform.Surfaces;
-using Avalonia.Platform;
-using Avalonia.Skia;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor
-{
- internal class BlazorSkiaRasterSurface : IBlazorSkiaSurface, IFramebufferPlatformSurface, IDisposable
- {
- public SKColorType ColorType { get; set; }
-
- public PixelSize Size { get; set; }
-
- public double Scaling { get; set; }
-
- private FramebufferData? _fbData;
- private readonly Action _blitCallback;
- private readonly Action _onDisposeAction;
-
- public BlazorSkiaRasterSurface(
- SKColorType colorType, PixelSize size, double scaling, Action blitCallback)
- {
- ColorType = colorType;
- Size = size;
- Scaling = scaling;
- _blitCallback = blitCallback;
- _onDisposeAction = Blit;
- }
-
- public void Dispose()
- {
- _fbData?.Dispose();
- _fbData = null;
- }
-
- public ILockedFramebuffer Lock()
- {
- var bytesPerPixel = 4; // TODO: derive from ColorType
- var dpi = Scaling * 96.0;
- var width = (int)(Size.Width * Scaling);
- var height = (int)(Size.Height * Scaling);
-
- if (_fbData is null || _fbData?.Size.Width != width || _fbData?.Size.Height != height)
- {
- _fbData?.Dispose();
- _fbData = new FramebufferData(width, height, bytesPerPixel);
- }
-
- var pixelFormat = ColorType.ToPixelFormat();
- var data = _fbData.Value;
- return new LockedFramebuffer(
- data.Address, data.Size, data.RowBytes,
- new Vector(dpi, dpi), pixelFormat, _onDisposeAction);
- }
-
- private void Blit()
- {
- if (_fbData != null)
- {
- var data = _fbData.Value;
- _blitCallback(data.Address, new SKSizeI(data.Size.Width, data.Size.Height));
- }
- }
-
- private readonly struct FramebufferData
- {
- public PixelSize Size { get; }
-
- public int RowBytes { get; }
-
- public IntPtr Address { get; }
-
- public FramebufferData(int width, int height, int bytesPerPixel)
- {
- Size = new PixelSize(width, height);
- RowBytes = width * bytesPerPixel;
- Address = Marshal.AllocHGlobal(width * height * bytesPerPixel);
- }
-
- public void Dispose()
- {
- Marshal.FreeHGlobal(Address);
- }
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/BlazorSkiaSurface.cs b/src/Web/Avalonia.Web.Blazor/BlazorSkiaSurface.cs
deleted file mode 100644
index fb49df338b..0000000000
--- a/src/Web/Avalonia.Web.Blazor/BlazorSkiaSurface.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Avalonia.Web.Blazor.Interop;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor
-{
- internal class BlazorSkiaSurface : IBlazorSkiaSurface
- {
- public BlazorSkiaSurface(GRContext context, SKHtmlCanvasInterop.GLInfo glInfo, SKColorType colorType, PixelSize size, double scaling, GRSurfaceOrigin origin)
- {
- Context = context;
- GlInfo = glInfo;
- ColorType = colorType;
- Size = size;
- Scaling = scaling;
- Origin = origin;
- }
-
- public SKColorType ColorType { get; set; }
-
- public PixelSize Size { get; set; }
-
- public GRContext Context { get; set; }
-
- public GRSurfaceOrigin Origin { get; set; }
-
- public double Scaling { get; set; }
-
- public SKHtmlCanvasInterop.GLInfo GlInfo { get; set; }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/ClipboardImpl.cs b/src/Web/Avalonia.Web.Blazor/ClipboardImpl.cs
deleted file mode 100644
index bafc07ca15..0000000000
--- a/src/Web/Avalonia.Web.Blazor/ClipboardImpl.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Avalonia.Input;
-using Avalonia.Input.Platform;
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor
-{
- internal class ClipboardImpl : IClipboard
- {
- public async Task GetTextAsync()
- {
- return await AvaloniaLocator.Current.GetRequiredService().
- InvokeAsync("navigator.clipboard.readText");
- }
-
- public async Task SetTextAsync(string text)
- {
- await AvaloniaLocator.Current.GetRequiredService().
- InvokeAsync("navigator.clipboard.writeText",text);
- }
-
- public async Task ClearAsync() => await SetTextAsync("");
-
- public Task SetDataObjectAsync(IDataObject data) => Task.CompletedTask;
-
- public Task GetFormatsAsync() => Task.FromResult(Array.Empty());
-
- public Task GetDataAsync(string format) => Task.FromResult(new());
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Cursor.cs b/src/Web/Avalonia.Web.Blazor/Cursor.cs
deleted file mode 100644
index d921b2fa6c..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Cursor.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using Avalonia.Input;
-using Avalonia.Platform;
-
-namespace Avalonia.Web.Blazor
-{
- public class CssCursor : ICursorImpl
- {
- public const string Default = "default";
- public string? Value { get; set; }
-
- public CssCursor(StandardCursorType type)
- {
- Value = ToKeyword(type);
- }
-
- ///
- /// Create a cursor from base64 image
- ///
- public CssCursor(string base64, string format, PixelPoint hotspot, StandardCursorType fallback)
- {
- Value = $"url(\"data:image/{format};base64,{base64}\") {hotspot.X} {hotspot.Y}, {ToKeyword(fallback)}";
- }
-
- ///
- /// Create a cursor from url to *.cur file.
- ///
- public CssCursor(string url, StandardCursorType fallback)
- {
- Value = $"url('{url}'), {ToKeyword(fallback)}";
- }
-
- ///
- /// Create a cursor from png/svg and hotspot position
- ///
- public CssCursor(string url, PixelPoint hotSpot, StandardCursorType fallback)
- {
- Value = $"url('{url}') {hotSpot.X} {hotSpot.Y}, {ToKeyword(fallback)}";
- }
-
- private static string ToKeyword(StandardCursorType type) => type switch
- {
- StandardCursorType.Hand => "pointer",
- StandardCursorType.Cross => "crosshair",
- StandardCursorType.Help => "help",
- StandardCursorType.Ibeam => "text",
- StandardCursorType.No => "not-allowed",
- StandardCursorType.None => "none",
- StandardCursorType.Wait => "progress",
- StandardCursorType.AppStarting => "wait",
-
- StandardCursorType.DragMove => "move",
- StandardCursorType.DragCopy => "copy",
- StandardCursorType.DragLink => "alias",
-
- StandardCursorType.UpArrow => "default",/*not found matching one*/
- StandardCursorType.SizeWestEast => "ew-resize",
- StandardCursorType.SizeNorthSouth => "ns-resize",
- StandardCursorType.SizeAll => "move",
-
- StandardCursorType.TopSide => "n-resize",
- StandardCursorType.BottomSide => "s-resize",
- StandardCursorType.LeftSide => "w-resize",
- StandardCursorType.RightSide => "e-resize",
- StandardCursorType.TopLeftCorner => "nw-resize",
- StandardCursorType.TopRightCorner => "ne-resize",
- StandardCursorType.BottomLeftCorner => "sw-resize",
- StandardCursorType.BottomRightCorner => "se-resize",
-
- _ => Default,
- };
-
- public void Dispose() {}
- }
-
- internal class CssCursorFactory : ICursorFactory
- {
- public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot)
- {
- using var imageStream = new MemoryStream();
- cursor.Save(imageStream);
-
- //not memory optimized because CryptoStream with ToBase64Transform is not supported in the browser.
- var base64String = Convert.ToBase64String(imageStream.ToArray());
- return new CssCursor(base64String, "png", hotSpot, StandardCursorType.Arrow);
- }
-
- ICursorImpl ICursorFactory.GetCursor(StandardCursorType cursorType)
- {
- return new CssCursor(cursorType);
- }
- }
-}
-
diff --git a/src/Web/Avalonia.Web.Blazor/IBlazorSkiaSurface.cs b/src/Web/Avalonia.Web.Blazor/IBlazorSkiaSurface.cs
deleted file mode 100644
index 5463893e27..0000000000
--- a/src/Web/Avalonia.Web.Blazor/IBlazorSkiaSurface.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Avalonia.Web.Blazor
-{
- internal interface IBlazorSkiaSurface
- {
- public PixelSize Size { get; set; }
-
- public double Scaling { get; set; }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/ActionHelper.cs b/src/Web/Avalonia.Web.Blazor/Interop/ActionHelper.cs
deleted file mode 100644
index 8bb266a942..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/ActionHelper.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.ComponentModel;
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class ActionHelper
- {
- private readonly Action action;
-
- public ActionHelper(Action action)
- {
- this.action = action;
- }
-
- [JSInvokable]
- public void Invoke() => action?.Invoke();
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class ActionHelper
- {
- private readonly Action action;
-
- public ActionHelper(Action action)
- {
- this.action = action;
- }
-
- [JSInvokable]
- public void Invoke(T param1) => action?.Invoke(param1);
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class ActionHelper
- {
- private readonly Action action;
-
- public ActionHelper(Action action)
- {
- this.action = action;
- }
-
- [JSInvokable]
- public void Invoke(T1 p1, T2 p2) => action?.Invoke(p1, p2);
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class ActionHelper
- {
- private readonly Action action;
-
- public ActionHelper(Action action)
- {
- this.action = action;
- }
-
- [JSInvokable]
- public void Invoke(T1 p1, T2 p2, T3 p3) => action?.Invoke(p1, p2, p3);
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- public class ActionHelper
- {
- private readonly Action action;
-
- public ActionHelper(Action action)
- {
- this.action = action;
- }
-
- [JSInvokable]
- public void Invoke(T1 p1, T2 p2, T3 p3, T4 p4) => action?.Invoke(p1, p2, p3, p4);
- }
-
-
-
-
-
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/AvaloniaModule.cs b/src/Web/Avalonia.Web.Blazor/Interop/AvaloniaModule.cs
deleted file mode 100644
index ff13e95aa7..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/AvaloniaModule.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class AvaloniaModule : JSModuleInterop
- {
- private AvaloniaModule(IJSRuntime js) : base(js, "./_content/Avalonia.Web.Blazor/Avalonia.js")
- {
- }
-
- public static async Task ImportAsync(IJSRuntime js)
- {
- var interop = new AvaloniaModule(js);
- await interop.ImportAsync();
- return interop;
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/DpiWatcherInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/DpiWatcherInterop.cs
deleted file mode 100644
index c86c72f29c..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/DpiWatcherInterop.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class DpiWatcherInterop : IDisposable
- {
- private const string StartSymbol = "DpiWatcher.start";
- private const string StopSymbol = "DpiWatcher.stop";
- private const string GetDpiSymbol = "DpiWatcher.getDpi";
-
- private event Action? callbacksEvent;
- private readonly ActionHelper _callbackHelper;
- private readonly AvaloniaModule _module;
-
- private DotNetObjectReference>? callbackReference;
-
- public DpiWatcherInterop(AvaloniaModule module, Action? callback = null)
- {
- _module = module;
- _callbackHelper = new ActionHelper((o, n) => callbacksEvent?.Invoke(n));
-
- if (callback != null)
- Subscribe(callback);
- }
-
- public void Dispose() => Stop();
-
- public void Subscribe(Action callback)
- {
- var shouldStart = callbacksEvent == null;
-
- callbacksEvent += callback;
-
- var dpi = shouldStart
- ? Start()
- : GetDpi();
-
- callback(dpi);
- }
-
- public void Unsubscribe(Action callback)
- {
- callbacksEvent -= callback;
-
- if (callbacksEvent == null)
- Stop();
- }
-
- private double Start()
- {
- if (callbackReference != null)
- return GetDpi();
-
- callbackReference = DotNetObjectReference.Create(_callbackHelper);
-
- return _module.Invoke(StartSymbol, callbackReference);
- }
-
- private void Stop()
- {
- if (callbackReference == null)
- return;
-
- _module.Invoke(StopSymbol);
-
- callbackReference?.Dispose();
- callbackReference = null;
- }
-
- public double GetDpi() => _module.Invoke(GetDpiSymbol);
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/FocusHelperInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/FocusHelperInterop.cs
deleted file mode 100644
index 090909f98f..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/FocusHelperInterop.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.AspNetCore.Components;
-
-namespace Avalonia.Web.Blazor.Interop;
-
-internal class FocusHelperInterop
-{
- private const string FocusSymbol = "FocusHelper.focus";
- private const string SetCursorSymbol = "FocusHelper.setCursor";
-
- private readonly AvaloniaModule _module;
- private readonly ElementReference _inputElement;
-
- public FocusHelperInterop(AvaloniaModule module, ElementReference inputElement)
- {
- _module = module;
- _inputElement = inputElement;
- }
-
- public void Focus() => _module.Invoke(FocusSymbol, _inputElement);
-
- public void SetCursor(string kind) => _module.Invoke(SetCursorSymbol, _inputElement, kind);
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/InputHelperInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/InputHelperInterop.cs
deleted file mode 100644
index 8872339f91..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/InputHelperInterop.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-using Microsoft.AspNetCore.Components;
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class WebCompositionEventArgs : EventArgs
- {
- public enum WebCompositionEventType
- {
- Start,
- Update,
- End
- }
-
- public WebCompositionEventArgs(string type, string data)
- {
- Type = type switch
- {
- "compositionstart" => WebCompositionEventType.Start,
- "compositionupdate" => WebCompositionEventType.Update,
- "compositionend" => WebCompositionEventType.End,
- _ => Type
- };
-
- Data = data;
- }
-
- public WebCompositionEventType Type { get; }
-
- public string Data { get; }
- }
-
- internal class WebInputEventArgs
- {
- public WebInputEventArgs(string type, string data)
- {
- Type = type;
- Data = data;
- }
-
- public string Type { get; }
-
- public string Data { get; }
-
- public bool Handled { get; set; }
- }
-
- internal class InputHelperInterop
- {
- private const string ClearSymbol = "InputHelper.clear";
- private const string FocusSymbol = "InputHelper.focus";
- private const string SetCursorSymbol = "InputHelper.setCursor";
- private const string HideSymbol = "InputHelper.hide";
- private const string ShowSymbol = "InputHelper.show";
- private const string StartSymbol = "InputHelper.start";
- private const string SetSurroundingTextSymbol = "InputHelper.setSurroundingText";
- private const string SetBoundsSymbol = "InputHelper.setBounds";
-
- private readonly AvaloniaModule _module;
- private readonly ElementReference _inputElement;
- private readonly ActionHelper _compositionAction;
- private readonly ActionHelper _inputAction;
-
- private DotNetObjectReference>? compositionActionReference;
- private DotNetObjectReference>? inputActionReference;
-
- public InputHelperInterop(AvaloniaModule module, ElementReference inputElement)
- {
- _module = module;
- _inputElement = inputElement;
-
- _compositionAction = new ActionHelper(OnCompositionEvent);
- _inputAction = new ActionHelper(OnInputEvent);
-
- Start();
- }
-
- public event EventHandler? CompositionEvent;
- public event EventHandler? InputEvent;
-
- private void OnCompositionEvent(string type, string data)
- {
- Console.WriteLine($"CompositionEvent Handler Helper {CompositionEvent == null} ");
- CompositionEvent?.Invoke(this, new WebCompositionEventArgs(type, data));
- }
-
- private void OnInputEvent(string type, string data)
- {
- Console.WriteLine($"InputEvent Handler Helper {InputEvent == null} ");
-
- var args = new WebInputEventArgs(type, data);
-
- InputEvent?.Invoke(this, args);
- }
-
- public void Clear() => _module.Invoke(ClearSymbol, _inputElement);
-
- public void Focus() => _module.Invoke(FocusSymbol, _inputElement);
-
- public void SetCursor(string kind) => _module.Invoke(SetCursorSymbol, _inputElement, kind);
-
- public void Hide() => _module.Invoke(HideSymbol, _inputElement);
-
- public void Show() => _module.Invoke(ShowSymbol, _inputElement);
-
- private void Start()
- {
- if(compositionActionReference != null)
- {
- return;
- }
-
- compositionActionReference = DotNetObjectReference.Create(_compositionAction);
-
- inputActionReference = DotNetObjectReference.Create(_inputAction);
-
- _module.Invoke(StartSymbol, _inputElement, compositionActionReference, inputActionReference);
- }
-
- public void SetSurroundingText(string text, int start, int end)
- {
- _module.Invoke(SetSurroundingTextSymbol, _inputElement, text, start, end);
- }
-
- public void SetBounds(PixelRect bounds, int caret)
- {
- _module.Invoke(SetBoundsSymbol, _inputElement, bounds.X, bounds.Y, bounds.Width, bounds.Height, caret);
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/JSModuleInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/JSModuleInterop.cs
deleted file mode 100644
index dca1b53650..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/JSModuleInterop.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class JSModuleInterop : IDisposable
- {
- private readonly Task moduleTask;
- private IJSUnmarshalledObjectReference? module;
-
- public JSModuleInterop(IJSRuntime js, string filename)
- {
- if (js is not IJSInProcessRuntime)
- throw new NotSupportedException("SkiaSharp currently only works on Web Assembly.");
-
- moduleTask = js.InvokeAsync("import", filename).AsTask();
- }
-
- public async Task ImportAsync()
- {
- module = await moduleTask;
- }
-
- public void Dispose()
- {
- OnDisposingModule();
- Module.Dispose();
- }
-
- protected IJSUnmarshalledObjectReference Module =>
- module ?? throw new InvalidOperationException("Make sure to run ImportAsync() first.");
-
- internal void Invoke(string identifier, params object?[]? args) =>
- Module.InvokeVoid(identifier, args);
-
- internal TValue Invoke(string identifier, params object?[]? args) =>
- Module.Invoke(identifier, args);
-
- internal ValueTask InvokeAsync(string identifier, params object?[]? args) =>
- Module.InvokeVoidAsync(identifier, args);
-
- internal ValueTask InvokeAsync(string identifier, params object?[]? args) =>
- Module.InvokeAsync(identifier, args);
-
- protected virtual void OnDisposingModule() { }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/NativeControlHostImpl.cs b/src/Web/Avalonia.Web.Blazor/Interop/NativeControlHostImpl.cs
deleted file mode 100644
index b824fcae46..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/NativeControlHostImpl.cs
+++ /dev/null
@@ -1,144 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-using Avalonia.Controls.Platform;
-using Avalonia.Platform;
-
-using Microsoft.AspNetCore.Components;
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop
-{
-
- internal class NativeControlHostInterop : INativeControlHostImpl
- {
- private const string CreateDefaultChildSymbol = "NativeControlHost.CreateDefaultChild";
- private const string CreateAttachmentSymbol = "NativeControlHost.CreateAttachment";
- private const string GetReferenceSymbol = "NativeControlHost.GetReference";
-
- private readonly AvaloniaModule _module;
- private readonly ElementReference _hostElement;
-
- public NativeControlHostInterop(AvaloniaModule module, ElementReference element)
- {
- _module = module;
- _hostElement = element;
- }
-
- public INativeControlHostDestroyableControlHandle CreateDefaultChild(IPlatformHandle parent)
- {
- var element = _module.Invoke(CreateDefaultChildSymbol);
- return new JSObjectControlHandle(element);
- }
-
- public INativeControlHostControlTopLevelAttachment CreateNewAttachment(Func create)
- {
- Attachment? a = null;
- try
- {
- using var hostElementJsReference = _module.Invoke(GetReferenceSymbol, _hostElement);
- var child = create(new JSObjectControlHandle(hostElementJsReference));
- var attachmenetReference = _module.Invoke(CreateAttachmentSymbol);
- // It has to be assigned to the variable before property setter is called so we dispose it on exception
-#pragma warning disable IDE0017 // Simplify object initialization
- a = new Attachment(attachmenetReference, child);
-#pragma warning restore IDE0017 // Simplify object initialization
- a.AttachedTo = this;
- return a;
- }
- catch
- {
- a?.Dispose();
- throw;
- }
- }
-
- public INativeControlHostControlTopLevelAttachment CreateNewAttachment(IPlatformHandle handle)
- {
- var attachmenetReference = _module.Invoke(CreateAttachmentSymbol);
- var a = new Attachment(attachmenetReference, handle);
- a.AttachedTo = this;
- return a;
- }
-
- public bool IsCompatibleWith(IPlatformHandle handle) => handle is JSObjectControlHandle;
-
- class Attachment : INativeControlHostControlTopLevelAttachment
- {
- private const string InitializeWithChildHandleSymbol = "InitializeWithChildHandle";
- private const string AttachToSymbol = "AttachTo";
- private const string ShowInBoundsSymbol = "ShowInBounds";
- private const string HideWithSizeSymbol = "HideWithSize";
- private const string ReleaseChildSymbol = "ReleaseChild";
-
- private IJSInProcessObjectReference? _native;
- private NativeControlHostInterop? _attachedTo;
-
- public Attachment(IJSInProcessObjectReference native, IPlatformHandle handle)
- {
- _native = native;
- _native.InvokeVoid(InitializeWithChildHandleSymbol, ((JSObjectControlHandle)handle).Object);
- }
-
- public void Dispose()
- {
- if (_native != null)
- {
- _native.InvokeVoid(ReleaseChildSymbol);
- _native.Dispose();
- _native = null;
- }
- }
-
- public INativeControlHostImpl? AttachedTo
- {
- get => _attachedTo!;
- set
- {
- CheckDisposed();
-
- var host = (NativeControlHostInterop?)value;
- if (host == null)
- {
- _native.InvokeVoid(AttachToSymbol);
- }
- else
- {
- _native.InvokeVoid(AttachToSymbol, host._hostElement);
- }
- _attachedTo = host;
- }
- }
-
- public bool IsCompatibleWith(INativeControlHostImpl host) => host is NativeControlHostInterop;
-
- public void HideWithSize(Size size)
- {
- CheckDisposed();
- if (_attachedTo == null)
- return;
-
- _native.InvokeVoid(HideWithSizeSymbol, Math.Max(1, (float)size.Width), Math.Max(1, (float)size.Height));
- }
-
- public void ShowInBounds(Rect bounds)
- {
- CheckDisposed();
-
- if (_attachedTo == null)
- throw new InvalidOperationException("Native control isn't attached to a toplevel");
-
- bounds = new Rect(bounds.X, bounds.Y, Math.Max(1, bounds.Width),
- Math.Max(1, bounds.Height));
-
- _native.InvokeVoid(ShowInBoundsSymbol, (float)bounds.X, (float)bounds.Y, (float)bounds.Width, (float)bounds.Height);
- }
-
- [MemberNotNull(nameof(_native))]
- private void CheckDisposed()
- {
- if (_native == null)
- throw new ObjectDisposedException(nameof(Attachment));
- }
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/SKHtmlCanvasInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/SKHtmlCanvasInterop.cs
deleted file mode 100644
index cf9350fb62..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/SKHtmlCanvasInterop.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using Microsoft.AspNetCore.Components;
-using Microsoft.JSInterop;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class SKHtmlCanvasInterop : IDisposable
- {
- private const string JsFilename = "./_content/Avalonia.Web.Blazor/SKHtmlCanvas.js";
- private const string InitGLSymbol = "SKHtmlCanvas.initGL";
- private const string InitRasterSymbol = "SKHtmlCanvas.initRaster";
- private const string DeinitSymbol = "SKHtmlCanvas.deinit";
- private const string RequestAnimationFrameSymbol = "SKHtmlCanvas.requestAnimationFrame";
- private const string SetCanvasSizeSymbol = "SKHtmlCanvas.setCanvasSize";
- private const string PutImageDataSymbol = "SKHtmlCanvas.putImageData";
-
- private readonly AvaloniaModule _module;
- private readonly ElementReference _htmlCanvas;
- private readonly string _htmlElementId;
- private readonly ActionHelper _callbackHelper;
-
- private DotNetObjectReference? callbackReference;
-
- public SKHtmlCanvasInterop(AvaloniaModule module, ElementReference element, Action renderFrameCallback)
- {
- _module = module;
- _htmlCanvas = element;
- _htmlElementId = element.Id;
-
- _callbackHelper = new ActionHelper(renderFrameCallback);
- }
-
- public void Dispose() => Deinit();
-
- public GLInfo InitGL()
- {
- if (callbackReference != null)
- throw new InvalidOperationException("Unable to initialize the same canvas more than once.");
-
- callbackReference = DotNetObjectReference.Create(_callbackHelper);
-
- return _module.Invoke(InitGLSymbol, _htmlCanvas, _htmlElementId, callbackReference);
- }
-
- public bool InitRaster()
- {
- if (callbackReference != null)
- throw new InvalidOperationException("Unable to initialize the same canvas more than once.");
-
- callbackReference = DotNetObjectReference.Create(_callbackHelper);
-
- return _module.Invoke(InitRasterSymbol, _htmlCanvas, _htmlElementId, callbackReference);
- }
-
- public void Deinit()
- {
- if (callbackReference == null)
- return;
-
- _module.Invoke(DeinitSymbol, _htmlElementId);
-
- callbackReference?.Dispose();
- }
-
- public void RequestAnimationFrame(bool enableRenderLoop) =>
- _module.Invoke(RequestAnimationFrameSymbol, _htmlCanvas, enableRenderLoop);
-
- public void SetCanvasSize(int rawWidth, int rawHeight) =>
- _module.Invoke(SetCanvasSizeSymbol, _htmlCanvas, rawWidth, rawHeight);
-
- public void PutImageData(IntPtr intPtr, SKSizeI rawSize) =>
- _module.Invoke(PutImageDataSymbol, _htmlCanvas, intPtr.ToInt64(), rawSize.Width, rawSize.Height);
-
- public record GLInfo(int ContextId, uint FboId, int Stencils, int Samples, int Depth);
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/SizeWatcherInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/SizeWatcherInterop.cs
deleted file mode 100644
index e21ae837d0..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/SizeWatcherInterop.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Microsoft.AspNetCore.Components;
-using Microsoft.JSInterop;
-using SkiaSharp;
-
-namespace Avalonia.Web.Blazor.Interop
-{
- internal class SizeWatcherInterop : IDisposable
- {
- private const string ObserveSymbol = "SizeWatcher.observe";
- private const string UnobserveSymbol = "SizeWatcher.unobserve";
-
- private readonly AvaloniaModule _module;
- private readonly ElementReference _htmlElement;
- private readonly string _htmlElementId;
- private readonly ActionHelper _callbackHelper;
-
- private DotNetObjectReference>? callbackReference;
-
- public SizeWatcherInterop(AvaloniaModule module, ElementReference element, Action callback)
- {
- _module = module;
- _htmlElement = element;
- _htmlElementId = element.Id;
- _callbackHelper = new ActionHelper((x, y) => callback(new SKSize(x, y)));
- }
-
- public void Dispose() => Stop();
-
- public void Start()
- {
- if (callbackReference != null)
- return;
-
- callbackReference = DotNetObjectReference.Create(_callbackHelper);
-
- _module.Invoke(ObserveSymbol, _htmlElement, _htmlElementId, callbackReference);
- }
-
- public void Stop()
- {
- if (callbackReference == null)
- return;
-
- _module.Invoke(UnobserveSymbol, _htmlElementId);
-
- callbackReference?.Dispose();
- callbackReference = null;
- }
- }
-}
diff --git a/src/Web/Avalonia.Web.Blazor/Interop/Storage/StorageProviderInterop.cs b/src/Web/Avalonia.Web.Blazor/Interop/Storage/StorageProviderInterop.cs
deleted file mode 100644
index 690d9683df..0000000000
--- a/src/Web/Avalonia.Web.Blazor/Interop/Storage/StorageProviderInterop.cs
+++ /dev/null
@@ -1,225 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-using Avalonia.Platform.Storage;
-
-using Microsoft.JSInterop;
-
-namespace Avalonia.Web.Blazor.Interop.Storage
-{
- internal record FilePickerAcceptType(string Description, IReadOnlyDictionary> Accept);
-
- internal record FileProperties(ulong Size, long LastModified, string? Type);
-
- internal class StorageProviderInterop : JSModuleInterop, IStorageProvider
- {
- private const string JsFilename = "./_content/Avalonia.Web.Blazor/Storage.js";
- private const string PickerCancelMessage = "The user aborted a request";
-
- public static async Task ImportAsync(IJSRuntime js)
- {
- var interop = new StorageProviderInterop(js);
- await interop.ImportAsync();
- return interop;
- }
-
- public StorageProviderInterop(IJSRuntime js)
- : base(js, JsFilename)
- {
- }
-
- public bool CanOpen => Invoke("StorageProvider.canOpen");
- public bool CanSave => Invoke("StorageProvider.canSave");
- public bool CanPickFolder => Invoke("StorageProvider.canPickFolder");
-
- public async Task> OpenFilePickerAsync(FilePickerOpenOptions options)
- {
- try
- {
- var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
-
- var (types, exludeAll) = ConvertFileTypes(options.FileTypeFilter);
- var items = await InvokeAsync("StorageProvider.openFileDialog", startIn, options.AllowMultiple, types, exludeAll);
- var count = items.Invoke("count");
-
- return Enumerable.Range(0, count)
- .Select(index => new JSStorageFile(items.Invoke("at", index)))
- .ToArray();
- }
- catch (JSException ex) when (ex.Message.Contains(PickerCancelMessage, StringComparison.Ordinal))
- {
- return Array.Empty();
- }
- }
-
- public async Task SaveFilePickerAsync(FilePickerSaveOptions options)
- {
- try
- {
- var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
-
- var (types, exludeAll) = ConvertFileTypes(options.FileTypeChoices);
- var item = await InvokeAsync("StorageProvider.saveFileDialog", startIn, options.SuggestedFileName, types, exludeAll);
-
- return item is not null ? new JSStorageFile(item) : null;
- }
- catch (JSException ex) when (ex.Message.Contains(PickerCancelMessage, StringComparison.Ordinal))
- {
- return null;
- }
- }
-
- public async Task> OpenFolderPickerAsync(FolderPickerOpenOptions options)
- {
- try
- {
- var startIn = (options.SuggestedStartLocation as JSStorageItem)?.FileHandle;
-
- var item = await InvokeAsync("StorageProvider.selectFolderDialog", startIn);
-
- return item is not null ? new[] { new JSStorageFolder(item) } : Array.Empty();
- }
- catch (JSException ex) when (ex.Message.Contains(PickerCancelMessage, StringComparison.Ordinal))
- {
- return Array.Empty();
- }
- }
-
- public async Task OpenFileBookmarkAsync(string bookmark)
- {
- var item = await InvokeAsync("StorageProvider.openBookmark", bookmark);
- return item is not null ? new JSStorageFile(item) : null;
- }
-
- public async Task OpenFolderBookmarkAsync(string bookmark)
- {
- var item = await InvokeAsync("StorageProvider.openBookmark", bookmark);
- return item is not null ? new JSStorageFolder(item) : null;
- }
-
- private static (FilePickerAcceptType[]? types, bool excludeAllOption) ConvertFileTypes(IEnumerable? input)
- {
- var types = input?
- .Where(t => t.MimeTypes?.Any() == true && t != FilePickerFileTypes.All)
- .Select(t => new FilePickerAcceptType(t.Name, t.MimeTypes!
- .ToDictionary(m => m, _ => (IReadOnlyList)Array.Empty())))
- .ToArray();
- if (types?.Length == 0)
- {
- types = null;
- }
-
- var inlcudeAll = input?.Contains(FilePickerFileTypes.All) == true || types is null;
-
- return (types, !inlcudeAll);
- }
- }
-
- internal abstract class JSStorageItem : IStorageBookmarkItem
- {
- internal IJSInProcessObjectReference? _fileHandle;
-
- protected JSStorageItem(IJSInProcessObjectReference fileHandle)
- {
- _fileHandle = fileHandle ?? throw new ArgumentNullException(nameof(fileHandle));
- }
-
- internal IJSInProcessObjectReference FileHandle => _fileHandle ?? throw new ObjectDisposedException(nameof(JSStorageItem));
-
- public string Name => FileHandle.Invoke("getName");
-
- public bool TryGetUri([NotNullWhen(true)] out Uri? uri)
- {
- uri = new Uri(Name, UriKind.Relative);
- return false;
- }
-
- public async Task GetBasicPropertiesAsync()
- {
- var properties = await FileHandle.InvokeAsync("getProperties");
-
- return new StorageItemProperties(
- properties?.Size,
- dateCreated: null,
- dateModified: properties?.LastModified > 0 ? DateTimeOffset.FromUnixTimeMilliseconds(properties.LastModified) : null);
- }
-
- public bool CanBookmark => true;
-
- public Task SaveBookmarkAsync()
- {
- return FileHandle.InvokeAsync("saveBookmark").AsTask();
- }
-
- public Task GetParentAsync()
- {
- return Task.FromResult(null);
- }
-
- public Task ReleaseBookmarkAsync()
- {
- return FileHandle.InvokeAsync("deleteBookmark").AsTask();
- }
-
- public void Dispose()
- {
- _fileHandle?.Dispose();
- _fileHandle = null;
- }
- }
-
- internal class JSStorageFile : JSStorageItem, IStorageBookmarkFile
- {
- public JSStorageFile(IJSInProcessObjectReference fileHandle) : base(fileHandle)
- {
- }
-
- public bool CanOpenRead => true;
- public async Task OpenReadAsync()
- {
- var stream = await FileHandle.InvokeAsync("openRead");
- // Remove maxAllowedSize limit, as developer can decide if they read only small part or everything.
- return await stream.OpenReadStreamAsync(long.MaxValue, CancellationToken.None);
- }
-
- public bool CanOpenWrite => true;
- public async Task OpenWriteAsync()
- {
- var properties = await FileHandle.InvokeAsync("getProperties");
- var streamWriter = await FileHandle.InvokeAsync("openWrite");
-
- return new JSWriteableStream(streamWriter, (long)(properties?.Size ?? 0));
- }
- }
-
- internal class JSStorageFolder : JSStorageItem, IStorageBookmarkFolder
- {
- public JSStorageFolder(IJSInProcessObjectReference fileHandle) : base(fileHandle)
- {
- }
-
- public async Task> GetItemsAsync()
- {
- var items = await FileHandle.InvokeAsync("getItems");
- if (items is null)
- {
- return Array.Empty();
- }
-
- var count = items.Invoke("count");
-
- return Enumerable.Range(0, count)
- .Select(index =>
- {
- var reference = items.Invoke("at", index);
- return reference.Invoke