Skip to content

D2Sharp wraps the D2 diagramming library for .NET, allowing you to render D2 diagrams with C# in your .NET applications.

License

Notifications You must be signed in to change notification settings

AlrikOlson/D2Sharp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

D2Sharp

A .NET wrapper for D2, the modern diagram scripting language that turns text to diagrams.

NuGet codecov License

Features

  • Zero Configuration - Works out of the box with sensible defaults
  • High Performance - Built-in worker pool handles concurrent requests efficiently
  • Full D2 Support - All D2 features: layouts, themes, sketch mode, and more
  • Async/Await - Task-based async rendering with cancellation support
  • Cross-Platform - Windows, macOS, and Linux
  • Production Ready - Battle-tested with comprehensive error handling

Installation

dotnet add package D2Sharp

Quick Start

using D2Sharp;

// Create a renderer (uses 3 worker processes by default)
using var renderer = new D2Renderer();

// Render a diagram
var result = await renderer.RenderDiagramAsync("A -> B -> C");

if (result.IsSuccess)
{
    File.WriteAllText("diagram.svg", result.Svg);
}
else
{
    Console.WriteLine($"Error: {result.Error?.Message}");
}

That's it! D2Sharp handles all the complexity for you.

Basic Usage

Simple Diagrams

using var renderer = new D2Renderer();

var script = @"
server -> database: queries
database -> cache: reads
";

var result = await renderer.RenderDiagramAsync(script);

Error Handling

var result = await renderer.RenderDiagramAsync("A -> ");  // Invalid

if (!result.IsSuccess)
{
    var error = result.Error;
    Console.WriteLine($"Line {error.LineNumber}: {error.Message}");
    Console.WriteLine($"  {error.LineContent}");
}

Synchronous Rendering

var result = renderer.RenderDiagram("A -> B");  // Blocks until complete

Cancellation & Timeouts

// With cancellation token
var cts = new CancellationTokenSource();
var result = await renderer.RenderDiagramAsync(script, cancellationToken: cts.Token);

// The renderer handles timeouts automatically - diagrams that take too long
// will be cancelled and return an error result

Customization

Themes

var options = new RenderOptions
{
    ThemeId = 1  // Cool classics theme
};

var result = await renderer.RenderDiagramAsync("server -> database", options);

300+ themes available: View all D2 themes →

Layout Engines

var options = new RenderOptions
{
    Layout = LayoutEngine.Elk  // or LayoutEngine.Dagre (default)
};
  • Dagre - Fast, clean layouts (default)
  • ELK - More complex layouts with additional features

Sketch Mode

var options = new RenderOptions
{
    Sketch = true  // Hand-drawn style
};

Visual Options

var options = new RenderOptions
{
    Pad = 50,        // Padding (default: 100)
    Scale = 0.5,     // Scale factor
    Center = true    // Center in viewbox
};

Combined Example

var options = new RenderOptions
{
    Layout = LayoutEngine.Elk,
    ThemeId = 1,
    Sketch = true,
    Pad = 75
};

var result = await renderer.RenderDiagramAsync(complexDiagram, options);

Advanced Configuration

Custom Worker Count

// For high-concurrency scenarios
using var renderer = new D2Renderer(workerCount: 15);

The default (3 workers) is optimal for most use cases.

ASP.NET Core Integration

// In Program.cs - Basic registration (uses 10 workers by default)
builder.Services.AddD2Sharp();

// With fluent configuration
builder.Services.AddD2Sharp(d2 => d2
    .UseProcessPool(pool => pool.WithWorkerCount(15))
    .ConfigureCaching(cache => cache.Enabled = true)
    .ConfigureTelemetry(telemetry => telemetry.EnableMetrics = true));

// Or use direct mode for CLI tools (no process pool)
builder.Services.AddD2Sharp(d2 => d2.UseDirect());

// In your controller/endpoint
public class DiagramController : ControllerBase
{
    private readonly D2Renderer _renderer;

    public DiagramController(D2Renderer renderer)
    {
        _renderer = renderer;
    }

    [HttpPost]
    public async Task<IActionResult> Render([FromBody] string script)
    {
        var result = await _renderer.RenderDiagramAsync(script);
        return result.IsSuccess
            ? Content(result.Svg, "image/svg+xml")
            : BadRequest(result.Error);
    }
}

Configuration Options

The fluent builder API provides several configuration options:

Process Pool Configuration

builder.Services.AddD2Sharp(d2 => d2
    .UseProcessPool(pool => pool.WithWorkerCount(15)));  // Customize worker count

Caching Configuration

builder.Services.AddD2Sharp(d2 => d2
    .ConfigureCaching(cache =>
    {
        cache.Enabled = true;
        cache.MaxSize = 500;
        cache.Expiration = TimeSpan.FromMinutes(30);
    }));

Telemetry Configuration

builder.Services.AddD2Sharp(d2 => d2
    .ConfigureTelemetry(telemetry =>
    {
        telemetry.EnableTracing = true;
        telemetry.EnableMetrics = true;
        telemetry.EnableDiagnosticIds = true;
    }));

Concurrency Limits (Direct Mode Only)

builder.Services.AddD2Sharp(d2 => d2
    .UseDirect()
    .ConfigureConcurrency(concurrency =>
    {
        concurrency.MaxConcurrentRenders = 5;
    }));

Combined Configuration

builder.Services.AddD2Sharp(d2 => d2
    .UseProcessPool(pool => pool.WithWorkerCount(20))
    .ConfigureCaching(cache => cache.Enabled = true)
    .ConfigureTelemetry(telemetry => telemetry.EnableMetrics = true));

Direct Mode (CLI Tools)

For command-line tools or single-threaded applications where you don't need worker processes:

using var renderer = D2Renderer.CreateDirect();
var result = await renderer.RenderDiagramAsync(script);

Note: Direct mode is not recommended for web applications with concurrent requests.

D2 Language Reference

# Shapes and connections
server -> client: HTTPS

# Containers
network: {
  router
  switch
  router -> switch
}

# Styling
server.style.fill: "#4CAF50"
client.shape: person

# Direction
direction: right

Learn D2 syntax →

Performance

D2Sharp is optimized for production workloads:

  • Concurrent requests: Efficiently handled via worker pool
  • Memory efficient: Automatic cleanup and minimal allocations
  • Fast: Simple diagrams render in ~30-50ms

Typical performance (on Apple Silicon):

  • Simple diagrams: 30-50ms
  • Complex diagrams: 100-200ms
  • Very complex: 300-500ms

Building from Source

Prerequisites

  • .NET 8.0 SDK
  • Go 1.22+
  • GCC

Check dependencies:

# Windows
.\depcheck.ps1

# Unix/Linux/macOS
./depcheck.sh

Build

dotnet build

Project Structure

  • src/D2Sharp - Main library
  • src/D2Sharp.Abstractions - Shared interfaces and types
  • src/D2Sharp.Worker - Worker process for process isolation
  • examples/D2Sharp.Web - Web demo application
  • tests/D2Sharp.Tests - Unit tests
  • tests/D2Sharp.IntegrationTests - Integration tests

Additional Documentation

Links

License

MIT License - see LICENSE.txt for details.

Acknowledgments

  • D2 - The diagram scripting language
  • Built with .NET 8.0

About

D2Sharp wraps the D2 diagramming library for .NET, allowing you to render D2 diagrams with C# in your .NET applications.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •