Skip to content

roostoph42/Skizzor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Skizzor

Skizzor is a configurable XAML→Razor transpiler, shipped as a NuGet package family. At its center sits a source- and target-neutral abstract UI tree (IR). Around it are swappable parsers (source side) and mappers (target side) — so any XAML dialect can be combined with any Razor component library, without the parser and mapper knowing about each other.

Architecture

flowchart LR
    A["<b>Avalonia</b><br/>(XAML)<br/><br/>Skizzor.Avalonia<br/><i>IXamlParser</i>"]
    S["<b>Skizzor</b><br/>abstract UI tree<br/>Parser · Mapper · Emit<br/><br/>Skizzor.Core"]
    B["<b>Blazor</b><br/>(Razor)<br/><br/>Skizzor.Radzen<br/><i>IComponentMapper</i>"]
    A -->|parse| S -->|emit| B
Loading

The data flow is a three-stage pipeline:

XAML ──▶ IXamlParser ──▶ [UI tree] ──▶ IComponentMapper ──▶ [UI tree] ──▶ RazorEmitter ──▶ Razor
         (source vocabulary)            (target vocabulary,                (target-neutral)
                                         emit-ready)
  • Parsers read a XAML dialect and populate the UI tree with source vocabulary (Button, {Binding}).
  • Mappers rewrite the tree into target vocabulary (ButtonRadzenButton) and lower source-specific values (bindings, resources, markup extensions) into emit-ready literals and expressions.
  • The emitter renders any emit-ready tree to Razor and lives in Core, because rendering is target-independent.

Packages

Package Role Status
Skizzor.Core IR (abstract UI tree), parser/mapper/emitter abstractions, pipeline, default emitter, diagnostics
Skizzor.Avalonia Parser for Avalonia XAML (AXAML), IXamlParser
Skizzor.Radzen Mapper onto Radzen Blazor components, IComponentMapper
Skizzor.Wpf Parser for WPF XAML planned
Skizzor.MudBlazor Mapper onto MudBlazor components planned

Usage

using Skizzor.Avalonia;
using Skizzor.Core.Pipeline;
using Skizzor.Radzen;

var pipeline = new TranspilerPipeline(new AvaloniaXamlParser(), new RadzenMapper());

var result = pipeline.Transpile(axaml);
if (result.Succeeded)
{
    Console.WriteLine(result.Code);
}
foreach (var diagnostic in result.Diagnostics)
{
    Console.WriteLine(diagnostic);
}

Example — from this AXAML …

<StackPanel Orientation="Vertical">
  <TextBlock Text="{Binding Title}" />
  <TextBox Text="{Binding Name, Mode=TwoWay}" />
  <Button Content="Save" Click="OnSave" IsEnabled="{Binding CanSave}" />
</StackPanel>

… Skizzor produces this Razor:

<RadzenStack Orientation="Vertical">
    <RadzenText Text="@(Title)" />
    <RadzenTextBox @bind-Value="Name" />
    <RadzenButton Text="Save" Click="@(OnSave)" IsEnabled="@(CanSave)" />
</RadzenStack>

Configurable mapping

The RadzenMapper is driven by a ComponentMap. The default set can be extended or overridden:

var map = RadzenMapper.CreateDefaultMap();
map.Map("Expander", "RadzenPanel")
   .MapAttribute("Header", "Text");

var mapper = new RadzenMapper(map);

Build

dotnet build

All packages target netstandard2.0 (maximum consumability, including from Roslyn source generators).

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages