Templar.Net
0.1.0
dotnet add package Templar.Net --version 0.1.0
NuGet\Install-Package Templar.Net -Version 0.1.0
<PackageReference Include="Templar.Net" Version="0.1.0" />
<PackageVersion Include="Templar.Net" Version="0.1.0" />
<PackageReference Include="Templar.Net" />
paket add Templar.Net --version 0.1.0
#r "nuget: Templar.Net, 0.1.0"
#:package Templar.Net@0.1.0
#addin nuget:?package=Templar.Net&version=0.1.0
#tool nuget:?package=Templar.Net&version=0.1.0
Templar
Indentation-aware template engine for C# codegen — multi-line values inherit the placeholder's column, trim/AOT-safe, zero dependencies.
The Problem
Standard template engines break indentation when substituting multi-line values:
// Template: // Output (broken):
class Foo class Foo
{ {
{{ body }} public void A()
} {
// ...
}
}
Templar's Solution
Continuation lines are padded to the placeholder's column:
// Template: // Output (correct):
class Foo class Foo
{ {
{{ body }} public void A()
} {
// ...
}
}
This works at arbitrary nesting depths and composes — inner templates render into outer templates with indentation preserved across boundaries.
Quick Start
Given a template file Templates/Calculator.tpl:
public static class {{ name }}
{
{{ body }}
}
Load it, fill it, render it:
using Templar.Rendering;
var set = new TemplateSet().AddDirectory("Templates");
var template = set.Get("Calculator");
template["name"] = "Calculator";
template["body"] = "public int Add(int a, int b)\n{\n return a + b;\n}";
Console.WriteLine(template.Render());
The multi-line body is injected at the {{ body }} column, so the rendered method body lines up one indent inside the class — no manual padding.
Syntax
| Form | Example | Effect |
|---|---|---|
| Variable | {{ name }} |
Replaced with value (empty if unset) |
| Filter | {{ name \| pascal }} |
Value transformed by filter |
| Comment | {{# ignored }} |
Stripped entirely from output |
| Conditional | {{? flag }}…{{?}} |
Body rendered when flag is truthy |
| Else branch | {{? flag }}…{{?else}}…{{?}} |
Second arm rendered when flag is falsy |
| Negation | {{?!flag }}…{{?}} |
Body rendered when flag is falsy |
| Escape | \{{ · \}} · \\ |
Literal {{, }}, \ |
Variable and filter names are case-insensitive. A conditional tests one variable by name — null, "", false, and an empty IEnumerable are falsy; everything else is truthy. Conditional tags are inline: keep {{? }}…{{?}} on the same line as the text they guard. A line containing only value placeholders that all render empty is dropped entirely, trailing newline included.
Built-in Filters
| Filter | Input | Output |
|---|---|---|
upper |
hello world |
HELLO WORLD |
lower |
Hello World |
hello world |
pascal |
hello_world |
HelloWorld |
camel |
hello_world |
helloWorld |
Custom filters: template.AddFilter("myFilter", val => ...).
Composition
The Compositor base class lets a class be a template: define Structure (the template text) and Templar auto-binds every readable instance property to a template variable matching the property name. The built-in CSharpFile preset provides a five-section structure for generating .cs files: header, pragmas, usings, file-scoped namespace, and body.
using Templar.Presets;
var file = new CSharpFile
{
Namespace = "MyApp.Generated",
Usings = new[] { "System", "System.Linq" },
Body = "public sealed class Foo;"
};
string output = file.Render();
See _docs/composition.md for the full pattern, including [TemplateBind], [TemplateIgnore], inheritance, and overriding Populate.
Sequences
A Sequence composes other values, rendering and joining them by a separator with the placeholder's indentation preserved on every line of every item. Construct one with new Sequence(items, separator), or use a built-in factory — Sequence.Lines (newline), Sequence.BlankLines (blank line between items), or Sequence.CommaList (, ); any plain IEnumerable<IComposable> value is joined by newline. CSharpFile uses one internally: its UsingsBlock is Sequence.Lines over Using compositors. Sequence, like Compositor, implements IComposable — the engine's composition primitive — so the two compose interchangeably.
Render Options
RenderOptions, applied via template.WithOptions(...) or TemplateSet.WithOptions(...), controls rendering:
| Option | Default | Effect |
|---|---|---|
IndentString |
four spaces | Unit of indentation for nested substitution |
Newline |
\n |
Output line ending; injected \r\n / \r are normalized to it |
StrictUndefined |
false |
When true, rendering a variable that was never set throws TemplateRenderException instead of emitting empty |
Templar is trim- and AOT-safe (IsTrimmable / IsAotCompatible), so it can be embedded in published, trimmed, or NativeAOT code generators.
Documentation
Long-form docs live in _docs/:
| Page | Covers |
|---|---|
| syntax.md | Placeholder, filter, comment, and indentation rules. |
| templates.md | Constructing, filling, and rendering a single template. |
| composition.md | Compositor, Sequence, attributes, the CSharpFile preset. |
| integration.md | TemplateSet, embedded resources, filter/options propagation, generators. |
| ui.md | Templar.UI — server-rendered HTML/XML/SVG component toolkit with auto-escaping. |
Build & Test
Requires .NET 10 SDK. Zero external dependencies.
dotnet build Templar.slnx
dotnet test Templar.slnx
License
Apache 2.0 — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 149 | 6/7/2026 |