LowlandTech.TinyTools
2026.5.31
dotnet add package LowlandTech.TinyTools --version 2026.5.31
NuGet\Install-Package LowlandTech.TinyTools -Version 2026.5.31
<PackageReference Include="LowlandTech.TinyTools" Version="2026.5.31" />
<PackageVersion Include="LowlandTech.TinyTools" Version="2026.5.31" />
<PackageReference Include="LowlandTech.TinyTools" />
paket add LowlandTech.TinyTools --version 2026.5.31
#r "nuget: LowlandTech.TinyTools, 2026.5.31"
#:package LowlandTech.TinyTools@2026.5.31
#addin nuget:?package=LowlandTech.TinyTools&version=2026.5.31
#tool nuget:?package=LowlandTech.TinyTools&version=2026.5.31
LowlandTech.TinyTools
LowlandTech.TinyTools is a lightweight .NET template engine for text generation, interpolation, and deterministic code generation. It is designed for data composition rather than HTML view rendering.
Install
dotnet add package LowlandTech.TinyTools
What it does
- Interpolates values into text templates
- Renders templates with
@if,@foreach, and comments - Supports pipe helpers and null-coalescing expressions
- Includes file-based template primitives for code generation workflows
- Targets
netstandard2.1,net8.0,net9.0, andnet10.0
Quick start
Basic interpolation
using LowlandTech.TinyTools;
var template = "Hello ${FirstName} ${LastName}!";
var model = new { FirstName = "Jane", LastName = "Doe" };
var result = template.Interpolate(model);
// Hello Jane Doe!
Dictionary interpolation
using LowlandTech.TinyTools;
var template = "Welcome to ${City}, ${Country}!";
var data = new Dictionary<string, string>
{
["City"] = "Amsterdam",
["Country"] = "Netherlands"
};
var result = template.Interpolate(data);
// Welcome to Amsterdam, Netherlands!
Full template engine
using LowlandTech.TinyTools;
var engine = new TinyTemplateEngine();
var context = new ToolContext();
context.Set("Name", "Alice");
context.Set("IsPremium", true);
context.Set("Items", new[] { "Item 1", "Item 2", "Item 3" });
var template = """
Hello ${Context.Name}!
@if (Context.IsPremium) {
Premium access is enabled.
} else {
Upgrade to premium.
}
Items:
@foreach (var item in Context.Items) {
- ${item}
}
""";
var output = engine.Render(template, context);
// Hello Alice!
//
// Premium access is enabled.
//
// Items:
// - Item 1
// - Item 2
// - Item 3
Template syntax
| Feature | Example |
|---|---|
| Variable interpolation | ${Context.Model.Name} |
| Null coalescing | ${Context.Title ?? "Untitled"} |
| Pipe helpers | ${Context.Name \| upper} |
| Conditionals | @if (Context.IsActive) { ... } |
| Else-if chains | } else if (Context.Score >= 80) { |
| Iteration | @foreach (var item in Context.Items) { ... } |
| Comments | @* ignored *@ |
Common use cases
- Generating Markdown, JSON, YAML, config files, or prompts
- Producing deterministic code generation output
- Keeping presentation-free templates outside MVC or Razor pipelines
- Building reusable file-based templates with validation hooks
Documentation
- Project site: https://tools.lowlandtech.com
- Source: https://github.com/lowlandtech/tinytools
- Docs folder: https://github.com/lowlandtech/tinytools/tree/develop/docs
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Ardalis.GuardClauses (>= 5.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Moq (>= 4.20.72)
- System.Text.Json (>= 10.0.8)
-
net10.0
- Ardalis.GuardClauses (>= 5.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Moq (>= 4.20.72)
-
net8.0
- Ardalis.GuardClauses (>= 5.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Moq (>= 4.20.72)
-
net9.0
- Ardalis.GuardClauses (>= 5.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Moq (>= 4.20.72)
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 |
|---|---|---|
| 2026.5.31 | 92 | 5/31/2026 |
| 2026.1.3 | 190 | 1/31/2026 |
| 2026.1.1 | 280 | 1/31/2026 |
| 2026.1.0 | 133 | 1/31/2026 |
| 2.0.1 | 2,653 | 7/18/2023 |
| 2.0.0 | 726 | 7/18/2023 |
| 1.6.2 | 6,449 | 8/8/2021 |
| 1.6.1 | 962 | 8/1/2021 |
| 1.0.5 | 932 | 7/23/2021 |
| 1.0.4 | 1,005 | 7/18/2021 |
| 1.0.3 | 950 | 7/16/2021 |
| 1.0.2 | 925 | 7/16/2021 |
| 1.0.1 | 919 | 6/15/2021 |
| 1.0.0 | 941 | 6/15/2021 |
# 2026.5.31
## Variable Syntax Update
### Breaking Changes
* Variable interpolation syntax changed from `{var}` to `${var}`
- Applies to simple interpolation tokens in templates and strings
- Aligns basic interpolation syntax with the engine's `${...}` expression model
- Reduces ambiguity between literal braces and interpolation tokens
### Migration Guide
**Before:**
```csharp
var template = "Hello {FirstName} {LastName}!";
```
**After:**
```csharp
var template = "Hello ${FirstName} ${LastName}!";
```
If you are using `ToolContext` or engine expressions, continue using `${Context.Name}` and `${...}` syntax consistently.
---
# 2026.1.3
## ITemplate System - Self-Validating Code Generation Templates
### New Features
* **ITemplate Interface** - Template-first approach to code generation
- Self-validating templates with embedded test cases
- Each template carries its own `TestDataJson` and `ExpectedContent`
- Automatic validation via `Validate()` and `ValidateDetailed()` methods
- Type-safe with `DataType` property for compile-time safety
* **TemplateBase Abstract Class** - Base implementation for templates
- Handles data serialization/normalization automatically
- Template rendering via `TinyTemplateEngine`
- Detailed validation with diff reporting
- Cross-platform line ending normalization
* **TemplateRegistry** - Centralized template management
- `Register()` / `Get()` for manual template registration
- `DiscoverFromAssembly()` - Auto-discover templates via reflection
- `DiscoverFromCallingAssembly()` - Discover from calling code
- `RenderBatch()` - Render multiple templates in one call
- `ValidateAll()` - Validate all registered templates at once
* **TemplateResult Record** - Rich rendering output
- `Content` - The rendered template content
- `Path` - Dynamic output path (supports variable interpolation)
- `Namespace` - Generated namespace
- `Metadata` - Optional key-value metadata dictionary
* **TinyTemplateEngine Enhancements**
- Logical AND operator (`&&`) in conditions
- Logical OR operator (`||`) in conditions
- Ternary expressions: `${Context.Active ? 'Yes' : 'No'}`
- Short-circuit evaluation for logical operators
- Parenthesized logical expressions
### Documentation
* New `Self-Validating-Templates.md` comprehensive guide
* Updated `ITemplate-QuickRef.md` with new syntax features
* New ITemplate page on documentation website (`/itemplate`)
* Template syntax reference cards
### Testing
* **Test count: 577 ? 633 tests (+56)**
* Fixed skipped test `ItShouldInterpolateFileExtension`
* `RenderBatch()` method tests (18 tests)
* `DiscoverFromAssembly()` method tests (21 tests)
* `ValidateAll()` edge case tests (10 tests)
* Null deserialization handling tests (3 tests)
* Exception handling in validation tests (4 tests)
### Infrastructure
* NCrunch configuration to exclude site folder
* VS Code launch configuration for site development
* Tasks configuration for npm dev server
### Examples
* `ComponentTemplate` - React component generator
* `CSharpClassTemplate` - C# class with properties/methods generator
---
# 2026.1.1
## Major Release - Template Services & Architecture Improvements
### New Features
* **Template Services Architecture** - Extensible service registration system
- Simple function-based services with string keys
- Syntax: `${Context.Services('serviceName')(input)}`
- Support for both string literals and variable references
- IoC-friendly design
* **Enhanced Variable Resolver**
- Method call support with string arguments
- Chained function calls (e.g., `Services('pluralize')('word')`)
- Direct delegate invocation
- Variable reference support in method calls
### Documentation
* Added comprehensive "Why TinyTemplateEngine?" section
* Template Services examples with Humanizer and NCalc
* Real-world usage examples (invoice generation, etc.)
* Sample implementations and best practices
### Architecture
* Introduced `ITemplateService` marker interface
* Added `TemplateServiceFunc` delegate type
* Context service inheritance to child contexts
* Error handling with clear "{service} not registered" messages
### Testing
* **Comprehensive test coverage expansion** - 1,100 ? 1,293 tests (+193)
* Complete test suite for template services
* Multi-language pluralization tests
* Calculator service tests
* Integration tests with real-world scenarios
* **TemplateHelpers test coverage:**
- `PadLeft` / `PadRight` helper tests
- `Round` (decimal/float), `Default`, `IfEmpty` tests
- `Floor`, `Ceiling`, `Count`, `First`, `Last`, `Reverse` tests
- `Format` helper tests (DateTime, DateTimeOffset, DateOnly, TimeOnly, IFormattable)
- `Register` custom helper tests
- `YesNo` and `IsEmpty` conditional helper tests
* **TinyTemplateEngine test coverage:**
- Negation operator tests (`!Context.Value`)
- Comparison operator edge cases
- `IsTruthy` method branch coverage
- `Compare` and `AreEqual` method tests
* **InterpolationExtensions test coverage:**
- `InterpolateWithEngine<T>` tests
- `Interpolate(ToolContext)` tests
- `Interpolate(List<string>, ToolContext)` tests
### Bug Fixes
* **Fixed delegate property resolution in VariableResolver** - `ToolContext.Get()` method was not being invoked for delegate properties, causing template services to fail silently
### Infrastructure
* Upgraded to .NET 8, 9, and 10 multi-targeting
* Modern GitHub Actions CI/CD workflows
* Cross-platform testing (Ubuntu, Windows, macOS)
* Code coverage integration
* Source Link support for better debugging
* Professional NuGet package metadata
### Dependencies
* Tests now include Humanizer.Core (2.14.1) for examples
* Tests now include NCalc (1.0.0) for calculator examples
* Added Microsoft.SourceLink.GitHub for source debugging
### Breaking Changes
* Removed built-in `pluralize` and `singularize` helpers from core
- Now available via Template Services pattern
- Keeps core library minimal and focused
### Migration Guide
**Before (2.0.x):**
```csharp
// Built-in helpers (removed)
var template = "${Context.EntityName | pluralize}";
```
**After (2026.1.1):**
```csharp
// Register as a service
context.RegisterService("pluralize", input => input?.ToString()?.Pluralize());
var template = "${Context.Services('pluralize')(Context.EntityName)}";
```
# 2.0.2
* add debug verification
# 2.0.1
* fix tests
# 2.0.0
* upgrade to .net 7
* upgrade dependencies
* remove support for legacy framework
* move from gitlab to github
# 1.6.1
* fix path bug
* add support for files and collection of templates
# 1.0.5
* make methods testharness virtual
* change namespaces for the unittests
# 1.0.4
* changed namespaces
* add test harness
* replace shouldy with fluentassertions
# 1.0.3
* add push for github
* add release notes
* add license
* remove csproj backup file
* fix bug in test
# 1.0.2:
* rearrange repository layout
* added ci
# 1.0.1
* added some more tests
# 1.0.0
* created interpolation extension for strings