diff --git a/README.md b/README.md
index c176946..2fecdcc 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ dotnet tool install -g Didot-cli
## QuickStart
-**Didot** is a command-line tool designed for generating files based on templating. It supports *YAML*, *JSON*, and *XML* as source data formats and provides flexibility in templating through both *Scriban*, *Liquid* and *Handlebars* templates languages. With Didot, you can easily automate file generation by combining structured data from YAML, JSON, or XML files with customizable templates using Scriban or DotLiquid.
+**Didot** is a command-line tool designed for generating files based on templating. It supports *YAML*, *JSON*, and *XML* as source data formats and provides flexibility in templating through both *Scriban*, *Liquid*, *Handlebars* and *SmartFormat* templates languages. With Didot, you can easily automate file generation by combining structured data from YAML, JSON, or XML files with customizable templates using Scriban or DotLiquid.
### Supported Data Formats:
@@ -55,14 +55,21 @@ Didot utilizes some templating engines, which allow for powerful and flexible te
- Highly performant, designed to handle large-scale template processing.
- Supports customizable scripting with rich expressions and filters.
- Can work with JSON and YAML data sources.
-- **dotLiquid**: Templates with the `.liquid` extension are parsed using a dotLiquid template engine. DotLiquid is a .NET port of the Liquid templating engine used by platforms like Shopify.
+ - Typical Use Case: Config file generation, reports, email templates, or any templating scenario not tied to a specific web framework.
+- **Liquid**: Templates with the `.liquid` extension are parsed using a dotLiquid template engine. DotLiquid is a .NET port of the Liquid templating engine used by platforms like Shopify.
- Secure (no access to system objects), making it ideal for user-generated templates.
- Allows both dynamic and static templating.
- Supports filters, tags, and various control flow structures.
+ - Typical Use Case: SaaS applications, dynamic content rendering, email templates.
- **Handlebars**: Templates with the `.hbs` extension are parsed using a Handlebars template engine. Handlebars C# port of the popular JavaScript Handlebars templating engine.
- Simple syntax for generating HTML or text files from templates.
- Support for helpers, partial templates, and block helpers.
- Good separation of logic from presentation.
+ - Typical Use Case: Email templates, reports, and content generation.
+- **SmartFormat**: Templates with the `.smart` extension are parsed using a SmartFormat template engine. SmartFormat.Net is a A lightweight templating engine primarily used for string formatting.
+ - Provides more advanced formatting capabilities than standard string formatting in C#.
+ - Supports nested templates, conditional formatting, and more.
+ - Typical Use Case: Log messages, report generation, and dynamic text formatting.
### Command Usage:
diff --git a/src/Didot.Core/Didot.Core.csproj b/src/Didot.Core/Didot.Core.csproj
index e29ef6b..d79afca 100644
--- a/src/Didot.Core/Didot.Core.csproj
+++ b/src/Didot.Core/Didot.Core.csproj
@@ -8,8 +8,9 @@
-
+
+
diff --git a/src/Didot.Core/TemplateEngines/DotLiquidWrapper.cs b/src/Didot.Core/TemplateEngines/DotLiquidWrapper.cs
index ce15188..fc11016 100644
--- a/src/Didot.Core/TemplateEngines/DotLiquidWrapper.cs
+++ b/src/Didot.Core/TemplateEngines/DotLiquidWrapper.cs
@@ -20,8 +20,6 @@ public string Render(Stream stream, dynamic model)
{
using var reader = new StreamReader(stream);
var template = reader.ReadToEnd();
- var templateInstance = Template.Parse(template);
- var hash = Hash.FromAnonymousObject(model);
- return templateInstance.Render(hash);
+ return Render(template, model);
}
}
diff --git a/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs b/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
index 868281e..b6162f9 100644
--- a/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
+++ b/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
@@ -14,6 +14,7 @@ public ITemplateEngine GetTemplateEngine(string extension)
".scriban" => new ScribanWrapper(),
".liquid" => new DotLiquidWrapper(),
".hbs" => new HandlebarsWrapper(),
+ ".smart" => new SmartFormatWrapper(),
_ => throw new NotSupportedException()
};
}
diff --git a/src/Didot.Core/TemplateEngines/SmartFormatWrapper.cs b/src/Didot.Core/TemplateEngines/SmartFormatWrapper.cs
new file mode 100644
index 0000000..c82de8b
--- /dev/null
+++ b/src/Didot.Core/TemplateEngines/SmartFormatWrapper.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SmartFormat;
+
+namespace Didot.Core.TemplateEngines;
+public class SmartFormatWrapper : ITemplateEngine
+{
+ public string Render(string template, dynamic model)
+ => Smart.Format(template, model);
+
+ public string Render(Stream stream, dynamic model)
+ {
+ using var reader = new StreamReader(stream);
+ var template = reader.ReadToEnd();
+ return Render(template, model);
+ }
+}
diff --git a/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs b/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
index 7412cdc..642b540 100644
--- a/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
+++ b/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
@@ -13,6 +13,7 @@ public class FileBasedTemplateEngineFactoryTests
[TestCase(".scriban", typeof(ScribanWrapper))]
[TestCase(".liquid", typeof(DotLiquidWrapper))]
[TestCase(".hbs", typeof(HandlebarsWrapper))]
+ [TestCase(".smart", typeof(SmartFormatWrapper))]
public void GetSourceParser_Extension_CorrectParser(string extension, Type expected)
{
var factory = new FileBasedTemplateEngineFactory();
diff --git a/testing/Didot.Core.Testing/TemplateEngines/SmartFormatWrapperTests.cs b/testing/Didot.Core.Testing/TemplateEngines/SmartFormatWrapperTests.cs
new file mode 100644
index 0000000..dd55c9e
--- /dev/null
+++ b/testing/Didot.Core.Testing/TemplateEngines/SmartFormatWrapperTests.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Didot.Core.TemplateEngines;
+using NUnit.Framework;
+
+namespace Didot.Core.Testing.TemplateEngines;
+public class SmartFormatWrapperTests
+{
+ [Test]
+ public void Render_SingleProperty_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var model = new Dictionary()
+ { { "Name", "World"} };
+ var result = engine.Render("Hello {model.Name}", new { model });
+ Assert.That(result, Is.EqualTo("Hello World"));
+ }
+
+ [Test]
+ public void Render_MultiProperty_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var model = new Dictionary()
+ { { "Name", "Albert"}, {"Age", 30 } };
+ var result = engine.Render("Hello {model.Name}. You're {model.Age} years old.", new { model });
+ Assert.That(result, Is.EqualTo("Hello Albert. You're 30 years old."));
+ }
+
+ [Test]
+ public void Render_NestedProperties_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var name = new Dictionary()
+ { { "First", "Albert"}, {"Last", "Einstein" } };
+ var model = new Dictionary()
+ { { "Name", name}, {"Age", 30 } };
+ var result = engine.Render("Hello {model.Name.First} {model.Name.Last}. Your age is {model.Age} years old.", new { model });
+ Assert.That(result, Is.EqualTo("Hello Albert Einstein. Your age is 30 years old."));
+ }
+
+ [Test]
+ public void Render_ArrayItems_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var albert = new Dictionary()
+ { { "Name", "Albert"}, {"Age", 30 } };
+ var nikola = new Dictionary()
+ { { "Name", "Nikola"}, {"Age", 50 } };
+ var model = new[] { albert, nikola };
+ var result = engine.Render("Hello {model[0].Name}. Your colleague is {model[1].Age} years old.", new { model });
+ Assert.That(result, Is.EqualTo("Hello Albert. Your colleague is 50 years old."));
+ }
+
+ [Test]
+ public void Render_ArrayLoop_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var albert = new Dictionary()
+ { { "Name", "Albert"}, {"Age", 30 } };
+ var nikola = new Dictionary()
+ { { "Name", "Nikola"}, {"Age", 50 } };
+ var model = new[] { albert, nikola };
+ var result = engine.Render("Hello {model:{Name}|, }!", new { model });
+ Assert.That(result, Is.EqualTo("Hello Albert, Nikola!"));
+ }
+
+ [Test]
+ public void Render_Stream_Successful()
+ {
+ var engine = new SmartFormatWrapper();
+ var model = new Dictionary()
+ { { "Name", "World"} };
+ using var stream = new MemoryStream(Encoding.UTF8.GetBytes("Hello {model.Name}"));
+ var result = engine.Render(stream, new { model });
+ Assert.That(result, Is.EqualTo("Hello World"));
+ }
+}