go-text-template
1.0.25-pr-47
See the version list below for details.
dotnet add package go-text-template --version 1.0.25-pr-47
NuGet\Install-Package go-text-template -Version 1.0.25-pr-47
<PackageReference Include="go-text-template" Version="1.0.25-pr-47" />
<PackageVersion Include="go-text-template" Version="1.0.25-pr-47" />
<PackageReference Include="go-text-template" />
paket add go-text-template --version 1.0.25-pr-47
#r "nuget: go-text-template, 1.0.25-pr-47"
#:package go-text-template@1.0.25-pr-47
#addin nuget:?package=go-text-template&version=1.0.25-pr-47&prerelease
#tool nuget:?package=go-text-template&version=1.0.25-pr-47&prerelease
text/template
This project is a C# adaptation of Go's template engine. It began as an experiment to see whether OpenAI Codex could port the Go implementation to .NET. Claude.AI helped with explanations and refinements along the way. The source code in this repository was largely produced by Codex with input from Claude.AI, and this README itself was also authored using Codex.
The original Go package can be found here:
- https://pkg.go.dev/text/template#pkg-overview
- https://cs.opensource.google/go/go/+/refs/tags/go1.24.4:src/text/template/template.go
Currently this repository demonstrates a relatively small but functional
implementation. The TemplateEngine.Process
helper reads templates using the
ANTLR-generated GoTemplateLexer
and GoTemplateParser
and performs variable
substitution, loops and conditionals.
Features
- Replace
{{ variable }}
placeholders with values from dictionaries or model objects. - Conditional blocks with
if
,else if
andelse
clauses. for
loops and Go-stylerange
loops over arrays, collections and maps.- Built-in functions:
eq
,ne
, numeric comparisons (lt
,le
,gt
,ge
), logical operators (and
,or
,not
) supporting multiple arguments. - Basic pipelines with the
lower
function for transforming output. - Access nested properties, map keys and indexes, including dynamic indexing via variables.
- Whitespace trimming with
{{-
and-}}
and comment syntax{{/* ... */}}
.
Example Scenarios
1. Variable Interpolation
Access properties
{{ .Property }}
Nested property access
{{ .User.Name }}
Index arrays or slices
{{ .Items[0] }}
Access map entries
{{ .Data.key }}
Control whitespace
{{- .Name -}}
2. Conditional Statements
Basic if
blocks
{{ if condition }}...{{ end }}
if
/else
blocks
{{ if condition }}...{{ else }}...{{ end }}
else if
chains
{{ if condition }}...{{ else if other }}...{{ end }}
Supported conditions include
{{ if .IsActive }}
{{ if eq .Status "active" }}
{{ if .User }}
3. Loop Statements
Iterate slices or arrays
{{ range .Items }}...{{ end }}
Capture index/value
{{ range $i, $v := .Items }}...{{ end }}
Iterate maps
{{ range .Map }}...{{ end }}
Map key/value variables
{{ range $k, $v := .Map }}...{{ end }}
Handle empty collections
{{ range .Items }}...{{ else }}...{{ end }}
4. Built-in Functions
Equality and inequality
eq
, ne
Numeric comparisons
lt
, le
, gt
, ge
Logical operators
and
, or
, not
5. Comments
Embedding comments
{{/* comment */}}
6. Pipelines
Chaining functions with |
{{ .Name | lower }}
Available pipeline helpers include
lower
- convert to lowercaseprint
- concatenate values using default formattingprintf
- printf-style formatting usingSprintfFormatter
html
- HTML escape the valuejs
- JavaScript escape the valueurlquery
- escape for URL query parameterslen
- length of a collection or stringindex
- retrieve an element by index or keyslice
- slice strings or listscall
- invoke a function value
Registered functions can be invoked via call
by name:
TemplateEngine.RegisterFunction("Add", new Func<int, int, int>((a, b) => a + b));
var result = TemplateEngine.Process("{{ call \"Add\" 1 2 }}", new {});
// result == "3"
Not Implemented Yet
with
,define
,template
andblock
directives.- Custom functions beyond basic comparisons and boolean operators.
- Custom delimiter support.
Usage
var tmpl = "Hello {{ .Name }}!";
var result = TemplateEngine.Process(tmpl, new { Name = "World" });
Console.WriteLine(result); // Hello World!
Example Template
string letter = @"Dear {{ .Name }}
{{ if .Attended }}
It was a pleasure to see you.
{{ else }}
Sorry you couldn't make it.
{{ end }}
You brought: {{ for item in Items }}{{ item }},{{ end }}
Thank you for the lovely {{ .Gift }}.";
var output = TemplateEngine.Process(letter, new
{
Name = "Bob",
Gift = "toaster",
Attended = false,
Items = new[] { "book", "pen" }
});
Console.WriteLine(output);
See the unit tests for more examples covering loops, conditionals and range expressions.
Claude's suggestions
https://gist.github.com/yetanotherchris/c80d0fadb5a2ee5b4beb0a4384020dbf.js
License
This project is released under the MIT license. Source code was produced by OpenAI Codex with assistance from Claude.AI. This README was written using OpenAI Codex.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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 was computed. 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. |
-
net9.0
- Antlr4.Runtime.Standard (>= 4.9.2)
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 |
---|---|---|
1.0.70 | 182 | 6/15/2025 |
1.0.67 | 176 | 6/15/2025 |
1.0.64 | 148 | 6/15/2025 |
1.0.62 | 158 | 6/15/2025 |
1.0.60 | 158 | 6/14/2025 |
1.0.57 | 171 | 6/14/2025 |
1.0.55 | 177 | 6/14/2025 |
1.0.53 | 176 | 6/14/2025 |
1.0.51 | 184 | 6/14/2025 |
1.0.48 | 184 | 6/14/2025 |
1.0.46 | 187 | 6/14/2025 |
1.0.43 | 314 | 6/12/2025 |
1.0.41 | 314 | 6/12/2025 |
1.0.37 | 310 | 6/12/2025 |
1.0.35 | 312 | 6/12/2025 |
1.0.30 | 298 | 6/12/2025 |
1.0.28 | 298 | 6/12/2025 |
1.0.27-pr-47 | 306 | 6/12/2025 |
1.0.26-pr-47 | 308 | 6/12/2025 |
1.0.25-pr-47 | 310 | 6/12/2025 |
1.0.24-pr-47 | 307 | 6/12/2025 |
1.0.23-pr-46 | 302 | 6/12/2025 |
1.0.22 | 308 | 6/12/2025 |
1.0.21-pr-44 | 300 | 6/12/2025 |
1.0.20 | 307 | 6/12/2025 |
1.0.19-pr-43 | 304 | 6/12/2025 |
1.0.18 | 307 | 6/12/2025 |
1.0.17-pr-42 | 304 | 6/12/2025 |
1.0.16 | 292 | 6/12/2025 |
1.0.15-pr-41 | 303 | 6/12/2025 |
1.0.14 | 312 | 6/12/2025 |
1.0.13-pr-40 | 304 | 6/12/2025 |
1.0.11 | 314 | 6/12/2025 |
1.0.10-pr-38 | 306 | 6/12/2025 |
1.0.9 | 313 | 6/12/2025 |
1.0.8-pr-36 | 302 | 6/12/2025 |
1.0.7-pr-35 | 313 | 6/12/2025 |
1.0.4 | 296 | 6/12/2025 |
1.0.3-pr-34 | 307 | 6/12/2025 |