diff --git a/zstring/.dockerignore b/zstring/.dockerignore new file mode 100644 index 00000000..af50df1a --- /dev/null +++ b/zstring/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/zstring/.gitignore b/zstring/.gitignore new file mode 100644 index 00000000..2cb90536 --- /dev/null +++ b/zstring/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +*.sln.iml +.idea/**/* +**/.idea/* \ No newline at end of file diff --git a/zstring/Apps/HelloApp.cs b/zstring/Apps/HelloApp.cs new file mode 100644 index 00000000..5822903b --- /dev/null +++ b/zstring/Apps/HelloApp.cs @@ -0,0 +1,102 @@ +using Ivy; +using Ivy.Shared; // for Colors.* +using Cysharp.Text; + +namespace IvyExamples.ZStringDemo.Apps; + +[App(icon: Icons.PartyPopper, title: "ZString Demo")] +public class HelloApp : ViewBase +{ + public override object Build() + { + // States for visible outputs + var concatState = this.UseState(); + var formatState = this.UseState(); + var joinState = this.UseState(); + var builderState = this.UseState(); + var preparedState = this.UseState(); + + return + Layout.Center() + | ( + Layout.Vertical().Gap(14).Padding(3) + + | Text.H2("ZString Demo in Ivy") + | Text.Block("Each section shows the **input** and the computed **output** so it’s clear what ZString does.") + + // ── Concat ─────────────────────────────────────────────────────────── + | new Card( + Layout.Vertical().Gap(8) + | Text.H3("1) Concat") + | Text.Markdown("**Input:** `\"Hello\" + \" \" + \"Ivy\" + \" \" + 2025`") + | new Button("Run Concat", () => + { + var output = ZString.Concat("Hello", " ", "Ivy", " ", 2025); + concatState.Value = output; + }) + | Text.Block($"Output: {concatState.Value ?? string.Empty}").Color(Colors.Green) + ) + + // ── Format ────────────────────────────────────────────────────────── + | new Card( + Layout.Vertical().Gap(8) + | Text.H3("2) Format") + | Text.Markdown("**Input:** `ZString.Format(\"Pi is {0:0.00}\", 3.14159)`") + | new Button("Run Format", () => + { + var output = ZString.Format("Pi is {0:0.00}", 3.14159); + formatState.Value = output; + }) + | Text.Block($"Output: {formatState.Value ?? string.Empty}").Color(Colors.Green) + ) + + // ── Join ──────────────────────────────────────────────────────────── + | new Card( + Layout.Vertical().Gap(8) + | Text.H3("3) Join") + | Text.Markdown("**Input:** `ZString.Join(\", \", new[] { \"A\", \"B\", \"C\" })`") + | new Button("Run Join", () => + { + var output = ZString.Join(", ", new[] { "A", "B", "C" }); + joinState.Value = output; + }) + | Text.Block($"Output: {joinState.Value ?? string.Empty}").Color(Colors.Green) + ) + + // ── StringBuilder ─────────────────────────────────────────────────── + | new Card( + Layout.Vertical().Gap(8) + | Text.H3("4) CreateStringBuilder") + | Text.Markdown("**Input:**" + + "\n```csharp\nusing var sb = ZString.CreateStringBuilder();\n" + + "sb.Append(\"foo\");\n" + + "sb.AppendLine(42);\n" + + "sb.AppendFormat(\"{0} {1:.###}\", \"bar\", 123.456789);\n" + + "var output = sb.ToString();\n```") + | new Button("Run StringBuilder", () => + { + using var sb = ZString.CreateStringBuilder(); + sb.Append("foo"); + sb.AppendLine(42); + sb.AppendFormat("{0} {1:.###}", "bar", 123.456789); + builderState.Value = sb.ToString(); + }) + | Text.Block($"Output:\n{builderState.Value ?? string.Empty}") + .Color(Colors.Purple) + ) + + // ── Prepared Format ───────────────────────────────────────────────── + | new Card( + Layout.Vertical().Gap(8) + | Text.H3("5) Prepared Format") + | Text.Markdown("**Input:** `var tpl = ZString.PrepareUtf16(\"x:{0}, y:{1:000}\"); tpl.Format(10, 20)`") + | new Button("Run Prepared Format", () => + { + var tpl = ZString.PrepareUtf16("x:{0}, y:{1:000}"); + preparedState.Value = tpl.Format(10, 20); + }) + | Text.Block($"Output: {preparedState.Value ?? string.Empty}").Color(Colors.Blue) + ) + ); + } +} diff --git a/zstring/Dockerfile b/zstring/Dockerfile new file mode 100644 index 00000000..02577622 --- /dev/null +++ b/zstring/Dockerfile @@ -0,0 +1,34 @@ +# Base runtime image +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +WORKDIR /app +EXPOSE 80 + +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src + +# Copy and restore +COPY ["Zstring.csproj", "./"] +RUN dotnet restore "Zstring.csproj" + +# Copy everything and build +COPY . . +RUN dotnet build "Zstring.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# Publish stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "Zstring.csproj" -c $BUILD_CONFIGURATION -o /app/publish + +# Final runtime image +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . + +# Set environment variables +ENV PORT=80 +ENV ASPNETCORE_URLS="http://+:80" + +# Run the executable +ENTRYPOINT ["dotnet","./Zstring.dll"] \ No newline at end of file diff --git a/zstring/GlobalUsings.cs b/zstring/GlobalUsings.cs new file mode 100644 index 00000000..9b2e2a08 --- /dev/null +++ b/zstring/GlobalUsings.cs @@ -0,0 +1,28 @@ +global using Ivy; +global using Ivy.Apps; +global using Ivy.Auth; +global using Ivy.Chrome; +global using Ivy.Client; +global using Ivy.Core; +global using Ivy.Core.Hooks; +global using Ivy.Helpers; +global using Ivy.Hooks; +global using Ivy.Shared; +global using Ivy.Views; +global using Ivy.Views.Alerts; +global using Ivy.Views.Blades; +global using Ivy.Views.Builders; +global using Ivy.Views.Charts; +global using Ivy.Views.Dashboards; +global using Ivy.Views.Forms; +global using Ivy.Views.Tables; +global using Ivy.Widgets.Inputs; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using System.Collections.Immutable; +global using System.ComponentModel.DataAnnotations; +global using System.Globalization; +global using System.Reactive.Linq; + +namespace Zstring; diff --git a/zstring/Program.cs b/zstring/Program.cs new file mode 100644 index 00000000..2b8ee7a7 --- /dev/null +++ b/zstring/Program.cs @@ -0,0 +1,12 @@ +using IvyExamples.ZStringDemo.Apps; + +CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US"); +var server = new Server(); +#if DEBUG +server.UseHotReload(); +#endif +server.AddAppsFromAssembly(); +server.AddConnectionsFromAssembly(); +var chromeSettings = new ChromeSettings().DefaultApp().UseTabs(preventDuplicates: true); +server.UseChrome(chromeSettings); +await server.RunAsync(); diff --git a/zstring/README.md b/zstring/README.md new file mode 100644 index 00000000..d82ccff8 --- /dev/null +++ b/zstring/README.md @@ -0,0 +1,17 @@ +# Ivy Example – ZString + +This example demonstrates the usage of **Cysharp.ZString** inside an Ivy application for high-performance string operations in .NET. + +The demo shows **both the inputs and the outputs** for: + +- `ZString.Concat` +- `ZString.Format` +- `ZString.Join` +- `ZString.CreateStringBuilder()` +- `ZString.PrepareUtf16<>` + +## Run Locally + +```bash +dotnet restore +dotnet watch --browse diff --git a/zstring/Zstring.csproj b/zstring/Zstring.csproj new file mode 100644 index 00000000..1cffd40b --- /dev/null +++ b/zstring/Zstring.csproj @@ -0,0 +1,23 @@ + + + + Exe + net9.0 + enable + enable + IvyExamples.ZStringDemo + IvyExamples.ZStringDemo + + + + + + + + + + + + + + diff --git a/zstring/Zstring.sln b/zstring/Zstring.sln new file mode 100644 index 00000000..c9c5a052 --- /dev/null +++ b/zstring/Zstring.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hello", "Zstring.csproj", "{039638F3-A6D7-FB67-E733-27BD896EFDC4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {039638F3-A6D7-FB67-E733-27BD896EFDC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {039638F3-A6D7-FB67-E733-27BD896EFDC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {039638F3-A6D7-FB67-E733-27BD896EFDC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {039638F3-A6D7-FB67-E733-27BD896EFDC4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5F74B1AD-6C2E-4FDA-9DAF-9F7D8053687B} + EndGlobalSection +EndGlobal diff --git a/zstring/assets/screenshot.png b/zstring/assets/screenshot.png new file mode 100644 index 00000000..261ff1f8 Binary files /dev/null and b/zstring/assets/screenshot.png differ