FlexRender.DependencyInjection 0.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FlexRender.DependencyInjection --version 0.1.0
                    
NuGet\Install-Package FlexRender.DependencyInjection -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FlexRender.DependencyInjection" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FlexRender.DependencyInjection" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="FlexRender.DependencyInjection" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FlexRender.DependencyInjection --version 0.1.0
                    
#r "nuget: FlexRender.DependencyInjection, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FlexRender.DependencyInjection@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FlexRender.DependencyInjection&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=FlexRender.DependencyInjection&version=0.1.0
                    
Install as a Cake Tool

FlexRender

NuGet NuGet Downloads CI License: MIT

A .NET library for rendering images from YAML templates with flexbox-like layout system. Perfect for generating receipts, labels, tickets, and other structured documents.

Features

  • YAML Templates - Define layouts in readable YAML format
  • Flexbox Layout - Row/column direction, wrap, justify, align, gap
  • Template Engine - Variables, loops (type: each), conditionals (type: if)
  • Multiple Content Types - Text, images, QR codes, barcodes
  • Output Formats - PNG, JPEG, BMP
  • CLI Tool - Render templates from command line
  • AOT Compatible - No reflection, works with Native AOT
  • Modular Architecture - Install only what you need

Examples

Receipt Dynamic Receipt Ticket Label
Receipt Dynamic Ticket Label

<details> <summary>Feature Showcase (click to expand)</summary>

Showcase

</details>

All examples are in the examples/ directory. Render them with the CLI:

flexrender render examples/receipt.yaml -d examples/receipt-data.json -o examples/output/receipt.png
flexrender render examples/ticket.yaml -d examples/ticket-data.json -o examples/output/ticket.png
flexrender render examples/receipt-dynamic.yaml -d examples/receipt-dynamic-data.json -o examples/output/receipt-dynamic.png

The receipt-dynamic.yaml demonstrates AST-level control flow with type: each for item lists and type: if for conditional sections.

Installation

dotnet add package FlexRender

Individual packages

Package Description
FlexRender.Core Layout engine, 0 external dependencies
FlexRender.Yaml YAML template parser
FlexRender.Skia SkiaSharp renderer
FlexRender.QrCode QR code support
FlexRender.Barcode Barcode support
FlexRender.DependencyInjection Microsoft DI integration
# Example: install only the core engine and YAML parser
dotnet add package FlexRender.Core
dotnet add package FlexRender.Yaml

# Or install the Skia renderer
dotnet add package FlexRender.Skia

Linux / Docker

SkiaSharp requires native libraries on Linux. If you get DllNotFoundException: libSkiaSharp, add the native assets package:

# Standard Linux (requires system fontconfig/freetype)
dotnet add package SkiaSharp.NativeAssets.Linux

# Minimal containers without system libs
dotnet add package SkiaSharp.NativeAssets.Linux.NoDependencies

CLI tool

dotnet tool install -g FlexRender.Cli

Dependency Injection

// Register all FlexRender services
services.AddFlexRender();

Quick Start

1. Create a template (receipt.yaml)

template:
  name: "receipt"
  version: 1

canvas:
  fixed: width
  width: 300
  background: "#ffffff"

layout:
  - type: flex
    padding: 20
    gap: 10
    children:
      - type: text
        content: "{{shopName}}"
        font: bold
        size: 1.5em
        align: center

      - type: flex
        gap: 4
        children:
          - type: each
            array: items
            as: item
            children:
              - type: flex
                direction: row
                justify: space-between
                children:
                  - type: text
                    content: "{{item.name}}"
                  - type: text
                    content: "{{item.price}} $"

      - type: text
        content: "Total: {{total}} $"
        font: bold
        size: 1.2em
        align: right

      - type: qr
        data: "{{paymentUrl}}"
        size: 100

2. Render with code

using FlexRender.Parsing;
using FlexRender.Rendering;
using FlexRender.Values;

var parser = new TemplateParser();
var renderer = new SkiaRenderer();

var template = parser.ParseFile("receipt.yaml");

var data = new ObjectValue
{
    ["shopName"] = "My Shop",
    ["total"] = 1500,
    ["paymentUrl"] = "https://pay.example.com/123",
    ["items"] = new ArrayValue(new TemplateValue[]
    {
        new ObjectValue { ["name"] = "Product 1", ["price"] = 500 },
        new ObjectValue { ["name"] = "Product 2", ["price"] = 1000 }
    })
};

// Render to bitmap (async API)
using var bitmap = await renderer.Render(template, data);

// Save to file
using var image = SKImage.FromBitmap(bitmap);
using var pngData = image.Encode(SKEncodedImageFormat.Png, 100);
using var stream = File.OpenWrite("receipt.png");
pngData.SaveTo(stream);

3. Or use CLI

flexrender render receipt.yaml -d data.json -o receipt.png

Template Syntax

Canvas Settings

canvas:
  fixed: width          # or height - which dimension is fixed
  size: 300             # size in pixels
  background: "#ffffff" # background color

Text Element

- type: text
  content: "Hello {{name}}!"
  font: main            # font reference
  size: 1.2em           # pixels, em, or percentage
  color: "#000000"
  align: center         # left/center/right
  wrap: true
  overflow: ellipsis    # ellipsis/clip/visible
  maxLines: 2
  rotate: none          # none/left/right/flip or degrees

Flex Container

- type: flex
  direction: row        # row/column
  wrap: wrap            # nowrap/wrap/wrap-reverse
  gap: 10
  padding: 5%
  justify: space-between  # start/center/end/space-between/space-around/space-evenly
  align: center           # start/center/end/stretch/baseline
  children:
    - type: text
      content: "Item"
      flex:
        grow: 1
        shrink: 0
        basis: auto

QR Code

- type: qr
  data: "{{url}}"
  size: 100
  errorCorrection: M    # L/M/Q/H
  foreground: "#000000"
  background: "#ffffff"

Barcode

- type: barcode
  data: "{{ean13}}"
  format: ean13         # ean13/ean8/code128/code39/upc
  width: 200
  height: 80
  showText: true
  foreground: "#000000"
  background: "#ffffff"

Image

- type: image
  src: "logo.png"       # or base64 from data
  width: 80%
  height: auto
  fit: contain          # contain/cover/fill/none

Template Expressions

Variable Substitution

# Simple variable
content: "Hello {{name}}"

# Nested access
content: "City: {{user.address.city}}"

# Array index
content: "First: {{items[0].name}}"

Loops (type: each)

# Iterate over array
- type: each
  array: items          # path to array in data
  as: item              # variable name for current item
  children:
    - type: text
      content: "{{item.name}}: {{item.price}}"

# Loop variables: @index, @first, @last
- type: each
  array: items
  as: item
  children:
    - type: text
      content: "{{@index}}. {{item.name}}"

Conditionals (type: if)

# Simple truthy check
- type: if
  condition: discount
  then:
    - type: text
      content: "Discount: {{discount}}%"

# With else branch
- type: if
  condition: premium
  then:
    - type: text
      content: "Premium member"
  else:
    - type: text
      content: "Regular member"

# Equality check
- type: if
  condition: status
  equals: "paid"
  then:
    - type: text
      content: "Payment received"
      color: "#22c55e"

# Chained else-if
- type: if
  condition: status
  equals: "paid"
  then:
    - type: text
      content: "PAID"
      color: "#22c55e"
  elseIf:
    condition: status
    equals: "pending"
    then:
      - type: qr
        data: "{{paymentUrl}}"
        size: 100
  else:
    - type: text
      content: "Payment required"
      color: "#ef4444"

CLI Commands

# Render template
flexrender render template.yaml -d data.json -o output.png
flexrender render template.yaml -d data.json -o output.jpg --quality 90
flexrender render template.yaml -d data.json -o output.bmp

# With base path for resolving relative fonts/images
flexrender render templates/receipt.yaml --base-path templates -o output.png

# Validate template
flexrender validate template.yaml

# Show template info
flexrender info template.yaml

# Debug layout - shows element bounds and hierarchy
flexrender debug-layout template.yaml -d data.json

# Watch mode - re-render on changes
flexrender watch template.yaml -d data.json -o preview.png

# Global options
--verbose, -v       # Verbose output
--fonts <dir>       # Custom fonts directory
--scale <float>     # Scale factor (e.g., 2.0 for retina)
--base-path <dir>   # Base path for resolving relative file references

API Reference

TemplateParser

var parser = new TemplateParser();

// Parse from string
Template template = parser.Parse(yamlString);

// Parse from file (with 1MB size limit)
Template template = parser.ParseFile("template.yaml");

// Check supported element types
IReadOnlyCollection<string> types = parser.SupportedElementTypes;
// Returns: ["text", "qr", "barcode", "image", "flex", "separator", "each", "if"]

TemplateExpander

Templates with type: each and type: if are automatically expanded during rendering. For manual expansion (useful for template caching):

var expander = new TemplateExpander();

// Expand control flow elements with data
Template expanded = expander.Expand(template, data);

// The expanded template has no Each/If elements - they're replaced with concrete elements
// This allows parsing once and rendering with different data

SkiaRenderer

using var renderer = new SkiaRenderer();

// Set base font size (default: 12)
renderer.BaseFontSize = 14f;

// Measure required size
SKSize size = renderer.Measure(template, data);

// Render to canvas
renderer.Render(canvas, template, data);
renderer.Render(canvas, template, data, offset: new SKPoint(10, 10));

// Render to bitmap
renderer.Render(bitmap, template, data);

// Async render via ILayoutRenderer<SKBitmap>
using var bitmap = await renderer.Render(template, data);

TemplateValue Types

// String
TemplateValue str = "hello";           // implicit conversion
TemplateValue str = new StringValue("hello");

// Number
TemplateValue num = 42;                // implicit from int
TemplateValue num = 3.14;              // implicit from double
TemplateValue num = new NumberValue(42);

// Boolean
TemplateValue flag = true;             // implicit conversion
TemplateValue flag = new BoolValue(true);

// Null
TemplateValue nil = NullValue.Instance;

// Array
var array = new ArrayValue(new TemplateValue[] { "a", "b", "c" });
int count = array.Count;
TemplateValue first = array[0];

// Object
var obj = new ObjectValue
{
    ["name"] = "John",
    ["age"] = 30,
    ["active"] = true
};
TemplateValue name = obj["name"];
bool has = obj.ContainsKey("name");

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on FlexRender.DependencyInjection:

Package Downloads
FlexRender

All-in-one FlexRender package. Linux/Docker: add SkiaSharp.NativeAssets.Linux to your project.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0 86 2/12/2026
0.7.2 305 2/11/2026
0.7.1 100 2/11/2026
0.7.0 102 2/11/2026
0.6.0 109 2/10/2026
0.5.2 112 2/10/2026
0.5.1 102 2/10/2026
0.5.0 102 2/10/2026
0.4.1 108 2/7/2026
0.3.1 122 2/6/2026
0.3.0 106 2/5/2026
0.2.0 130 2/5/2026
0.1.0 113 2/5/2026
0.0.4 107 2/4/2026
0.0.3 158 2/4/2026