diff --git a/docs/_data/navigation_docs.yml b/docs/_data/navigation_docs.yml
index 25b0abd..d338dd7 100644
--- a/docs/_data/navigation_docs.yml
+++ b/docs/_data/navigation_docs.yml
@@ -15,5 +15,7 @@
- title: Usage
docs:
- supported-format-engine
+ - cli-options
- basic-usage
- - other-options
\ No newline at end of file
+ - use-stdin-stdout
+ - specify-engine-parser
\ No newline at end of file
diff --git a/docs/_docs/cli-options.md b/docs/_docs/cli-options.md
new file mode 100644
index 0000000..3fe4ab7
--- /dev/null
+++ b/docs/_docs/cli-options.md
@@ -0,0 +1,104 @@
+---
+title: CLI options
+tags: [quick-start, cli-usage]
+---
+## General format for options
+
+### Shortcut Option (Single Character)
+
+Shortcut options are prefixed with a single hyphen (-) and can be followed directly by the value without a space, though a space can be used if preferred.
+**Example:**
+
+- Without space: `-tpath/to/template`
+- With space: `-t path/to/template`
+
+### Long Version Option (Double Dash)
+
+Long options are prefixed with double hyphens (--), the first letter of the option is uppercase, and the option name is followed by an equal sign (=) to assign its value.
+**Example:** `--Template=path/to/template`
+
+## Option Values
+
+### Single Value
+
+An option can take a single value, which is provided right after the shortcut or the `=` sign for long options.
+**Example**: `-s path/to/source` or `--Source=path/to/source`
+
+### Switch Values
+
+If an option accepts a boolean, this one can be omitted.
+**Example**: `-i` or `--StdIn` or `--StdIn=true`
+
+### Multiple Values
+
+If an option accepts multiple values, the values should be separated by a semicolon (;).
+**Example**: `--Sources=file1.yaml;file2.json;file3.xml`
+
+### Key-Value Pairs
+
+For key-value pairs, the key is followed by a colon (:), and then the value. Multiple key-value pairs, if allowed, should be separated by a semicolon (;).
+**Example**: `--Extensions=txt:handlebars;liquid:fluid`
+
+## Didot Options Explained
+
+### Template Option
+
+Shortcut: `-t`
+Long: `--Template`
+Description: Specifies the path to the template file.
+Accept: single value.
+Mandatory: yes.
+Example: `-tpath/to/template` or `--Template=path/to/template`
+
+### Engine option
+
+Shortcut: -e
+Long: --Engine
+Description: Specifies the template engine to use (scriban, fluid, dotliquid, handlebars, smartformat, stringtemplate).
+Accept: single value. When omitted Didot will select the engine based on the extension of the template file.
+Example: `-efluid` or `--Engine=fluid`
+
+### Source Option
+
+Shortcut: `-s`
+Long: `--Source`
+Description: Specifies the path to the source file. If omitted, input can be taken from StdIn.
+Accept: single value.
+Exclusive: can't be set with the parameter `--StdIn`
+Example: `-spath/to/source` or `--Source=path/to/source`
+
+### Parser Option
+
+Shortcut: -p
+Long: --Parser
+Description: Specifies the parser to use (YAML, JSON, XML).
+Accept: single value.
+Mandatory: no expect if `--StdIn` is specified. When omitted Didot will select the parser based on the extension of the source file
+Example: `-pYAML` or `--Parser=YAML`
+
+### StdIn Option
+
+Shortcut: `-i`
+Long: --StdIn
+Description: Specifies the input to the source data as coming from the StdIn.
+Accept: switch value.
+Exclusive: can't be set with the parameter `--Source`
+Example: `-i` or `--StdIn`
+
+### Output Option
+
+Shortcut: `-o`
+Long: `--Output`
+Description: Specifies the path to the generated output file. If omitted, output is rendered to StdOut.
+Accept: single value.
+Mandatory: no.
+Example: `-opath/to/output` or `--Output=path/to/output`
+
+### Extension option
+
+Shortcut: -x
+Long: --Extension
+Description: Specifies additional or replacing link between extensions and engine for automatic detection
+Accept: multiple key-value pairs.
+Mandatory: no.
+Example: `-xtxt:handlebars;liquid:fluid` or `--Extension=txt:handlebars;liquid:fluid`
diff --git a/docs/_docs/installation-windows.md b/docs/_docs/installation-windows.md
index 8d9ea26..837c967 100644
--- a/docs/_docs/installation-windows.md
+++ b/docs/_docs/installation-windows.md
@@ -10,7 +10,7 @@ tags: [quick-start, installation]
Example:
- ```pwsh
+ ```powershell
https://github.com/Seddryck/Didot/releases/download/v0.13.0/Didot-0.13.0-net7.0-win-x64.zip
```
diff --git a/docs/_docs/specify-engine-parser.md b/docs/_docs/specify-engine-parser.md
new file mode 100644
index 0000000..aee43a1
--- /dev/null
+++ b/docs/_docs/specify-engine-parser.md
@@ -0,0 +1,58 @@
+---
+title: Specify template engine or parser
+tags: [cli-usage]
+---
+## Specify the data parser
+
+- `-p, --Parser`: Defines the parser to use when the source data is provided through the console. Accepted values are `yaml`, `json` or `xml`. This option is required only when the `--Source` argument is omitted or if the extension of the source file is not recognized to determine the parser.
+
+```powershell
+didot -t template.hbs -s data.txt -p json -o output.txt
+```
+
+In this example:
+
+- `template.hbs` is the Handlebars template file.
+- `data.txt` is the source file.
+- `json` is the parser of input data from the source file.
+- `output.txt` is the file where the output will be rendered.
+
+## Specify the template engine
+
+### Direct specification
+
+- `-e, --Engine`: Defines the template engine to use independantly of the template file extension. Accepted values are `scriban`, `dotliquid`, `fluid`, `handlebars`, `stringtemplate`, `smartformat`.
+
+```powershell
+didot -t template.txt -s data.json -e handlebars -o output.txt
+```
+
+In this example:
+
+- `template.txt` is the template file.
+- `data.json` is the data JSON file.
+- `handlebars` is the template engine to use.
+- `output.txt` is the file where the output will be rendered.
+
+### Add or replace extension associations
+
+- `-x, --Extensions`: Defines the association of a file's extension with a template engine. More than one can be specified.
+
+```powershell
+didot -t template.txt -s data.json -x txt:handlebars;liquid:fluid -o output.txt
+```
+
+In this example:
+
+- `template.txt` is the template file.
+- `data.json` is the data JSON file.
+- `txt:handlebars;liquid:fluid` is associating Handlbars to the extension `.txt` and Fluid to the extension `.liquid`.
+- `output.txt` is the file where the output will be rendered.
+
+By default following file's extension association are registered:
+
+- `.scriban` to Scriban
+- `.liquid` to DotLiquid
+- `.hbs` to Handlebars
+- `.smart` to SmartFormat
+- `.st` and `.stg` to StringTemplate
diff --git a/docs/_docs/supported-format-engine.md b/docs/_docs/supported-format-engine.md
index 97d39b3..1c7252c 100644
--- a/docs/_docs/supported-format-engine.md
+++ b/docs/_docs/supported-format-engine.md
@@ -19,11 +19,17 @@ Didot utilizes some templating engines, which allow for powerful and flexible te
- Supports customizable scripting with rich expressions and filters.
- Can work with JSON and YAML data sources.
- 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.
+- **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.
- 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.
+- **Fluid**: Fully compatible with `.liquid` templates. The Fluid template engine is a fast and secure .NET-based port of the Liquid templating language.
+ - Optimized for performance, with careful memory management and faster parsing.
+ - Highly secure (does not expose system objects) and well-suited for user-generated content and environments requiring strict control over input and output.
+ - Rich templating features, supporting filters, tags, loops, and conditionals.
+ - Flexible and customizable, making it easy to extend the engine with custom filters or tags.
+ - Typical Use Case: Applications with complex data bindings, dynamic content generation in websites, CMS platforms, and document templating systems.
- **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.
diff --git a/docs/_docs/other-options.md b/docs/_docs/use-stdin-stdout.md
similarity index 96%
rename from docs/_docs/other-options.md
rename to docs/_docs/use-stdin-stdout.md
index dfc20af..9b91b6d 100644
--- a/docs/_docs/other-options.md
+++ b/docs/_docs/use-stdin-stdout.md
@@ -1,5 +1,5 @@
---
-title: Other options
+title: Usage of StdIn and StdOut
tags: [cli-usage]
---
## With data from the console
@@ -8,7 +8,7 @@ tags: [cli-usage]
- `-p, --Parser`: Defines the parser to use when the source data is provided through the console. Accepted values are `yaml`, `json` or `xml`. This option is required only when the `--Source` argument is omitted or if the extension of the source file is not recognized to determine the parser.
CMD:
-```cmd
+```bash
type data.json | didot --StdIn -t template.hbs -p json -o output.txt
```
diff --git a/src/Didot.Cli/Options.cs b/src/Didot.Cli/Options.cs
index bbae77d..a4d81e8 100644
--- a/src/Didot.Cli/Options.cs
+++ b/src/Didot.Cli/Options.cs
@@ -20,6 +20,12 @@ public class Options
[Option('p', "Parser", Required = false, HelpText = "The parser to use when reading from StdIn.")]
public string? Parser { get; set; }
+ [Option('e', "Engine", Required = false, HelpText = "Force a specific engine.")]
+ public string? Engine { get; set; }
+
+ [Option('x', "Extension", Required = false, Separator = ';', HelpText = "Associate an extension to a specific engine.")]
+ public required IEnumerable Extensions { get; set; }
+
[Option('o', "Output", Required = false, HelpText = "Path to the generated file.")]
public string? Output { get; set; }
}
diff --git a/src/Didot.Cli/Program.cs b/src/Didot.Cli/Program.cs
index 3fc0303..13b55d8 100644
--- a/src/Didot.Cli/Program.cs
+++ b/src/Didot.Cli/Program.cs
@@ -49,9 +49,7 @@ static Stream copyInStream()
var parserFactory = new FileBasedSourceParserFactory();
var parser = parserFactory.GetSourceParser(sourceExtension);
- var templateExtension = new FileInfo(opts.Template).Extension;
- var engineFactory = new FileBasedTemplateEngineFactory();
- var engine = engineFactory.GetTemplateEngine(templateExtension);
+ var engine = GetTemplateEngine(opts);
var printer = new Printer(engine, parser);
using var template = File.OpenRead(opts.Template);
@@ -63,9 +61,42 @@ static Stream copyInStream()
File.WriteAllText(opts.Output, output);
}
+ private static ITemplateEngine GetTemplateEngine(Options opts)
+ {
+ var engineFactory = new FileBasedTemplateEngineFactory();
+ if (opts.Engine is not null)
+ return engineFactory.GetTemplateEngineByTag(opts.Engine);
+ else
+ {
+ if (opts.Extensions is not null && opts.Extensions.Any())
+ {
+ foreach (var extensionAssociation in opts.Extensions)
+ {
+ if (!string.IsNullOrWhiteSpace(extensionAssociation))
+ {
+ var split = extensionAssociation.Split(':');
+ if (split.Length != 2)
+ throw new Exception(extensionAssociation);
+ (string extension, var engineTag) = (split[0], split[1]);
+ var engineInstance = engineFactory.GetTemplateEngineByTag(engineTag);
+ engineFactory.AddOrReplaceEngine(extension, engineInstance);
+ }
+ }
+ }
+ var templateExtension = new FileInfo(opts.Template).Extension;
+ return engineFactory.GetTemplateEngineByExtension(templateExtension);
+ }
+ }
+
static void HandleParseError(IEnumerable errs)
{
- // Handle errors here (e.g., show help message)
- System.Console.WriteLine("Error parsing arguments.");
+ Console.WriteLine("Error parsing arguments.");
+ foreach (var error in errs)
+ {
+ if (error is UnknownOptionError unknown)
+ Console.WriteLine($"{unknown.Tag}: {unknown.Token}");
+ else
+ Console.WriteLine(error);
+ }
}
}
diff --git a/src/Didot.Core/Didot.Core.csproj b/src/Didot.Core/Didot.Core.csproj
index 4464765..ce20192 100644
--- a/src/Didot.Core/Didot.Core.csproj
+++ b/src/Didot.Core/Didot.Core.csproj
@@ -8,6 +8,7 @@
+
diff --git a/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs b/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
index 796c0e6..21cad84 100644
--- a/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
+++ b/src/Didot.Core/TemplateEngines/FileBasedTemplateEngineFactory.cs
@@ -8,14 +8,73 @@
namespace Didot.Core.TemplateEngines;
public class FileBasedTemplateEngineFactory
{
- public ITemplateEngine GetTemplateEngine(string extension)
- => extension.ToLowerInvariant() switch
+ protected Dictionary engines = new();
+
+ public FileBasedTemplateEngineFactory()
+ {
+ Initialize();
+ }
+
+ protected virtual void Initialize()
+ {
+ engines.Clear();
+ engines.Add(".scriban", new ScribanWrapper());
+ engines.Add(".liquid", new DotLiquidWrapper());
+ engines.Add(".hbs", new HandlebarsWrapper());
+ engines.Add(".smart", new SmartFormatWrapper());
+ engines.Add(".st", new StringTemplateWrapper());
+ engines.Add(".stg", new StringTemplateWrapper());
+ }
+
+ public virtual void AddOrReplaceEngine(string extension, ITemplateEngine engine)
+ {
+ extension = NormalizeExtension(extension);
+
+ if (engines.ContainsKey(extension))
+ engines[extension] = engine;
+ else
+ engines.Add(extension, engine);
+ }
+
+ protected virtual string NormalizeExtension(string extension)
+ {
+ extension = extension.Trim().ToLowerInvariant();
+ if (!extension.StartsWith('.'))
+ extension = $".{extension}";
+ return extension;
+ }
+
+ public ITemplateEngine GetTemplateEngineByExtension(string extension)
+ {
+ extension = NormalizeExtension(extension);
+ if (engines.TryGetValue(extension, out var engine))
+ return engine;
+ throw new NotSupportedException(nameof(extension));
+ }
+
+ public Dictionary ListEngineByTags()
+ {
+ var asm = typeof(ITemplateEngine).Assembly;
+ var types = asm.GetTypes()
+ .Where(t => t.Namespace == GetType().Namespace
+ && typeof(ITemplateEngine).IsAssignableFrom(t)
+ && !t.IsInterface
+ && !t.IsAbstract);
+
+ var dict = new Dictionary();
+ foreach (var type in types)
{
- ".scriban" => new ScribanWrapper(),
- ".liquid" => new DotLiquidWrapper(),
- ".hbs" => new HandlebarsWrapper(),
- ".smart" => new SmartFormatWrapper(),
- ".st" or ".stg" => new StringTemplateWrapper(),
- _ => throw new NotSupportedException()
- };
+ var tag = type.Name.Replace("Wrapper", string.Empty).Trim().ToLowerInvariant();
+ dict.Add(tag, type);
+ }
+ return dict;
+ }
+
+ public ITemplateEngine GetTemplateEngineByTag(string tag)
+ {
+ tag = tag.Trim().ToLowerInvariant();
+ if (!ListEngineByTags().TryGetValue(tag, out var engineType))
+ throw new Exception(tag);
+ return (ITemplateEngine)Activator.CreateInstance(engineType)!;
+ }
}
diff --git a/src/Didot.Core/TemplateEngines/FluidWrapper.cs b/src/Didot.Core/TemplateEngines/FluidWrapper.cs
new file mode 100644
index 0000000..b5b9e0e
--- /dev/null
+++ b/src/Didot.Core/TemplateEngines/FluidWrapper.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Fluid;
+using SmartFormat.Core.Extensions;
+
+namespace Didot.Core.TemplateEngines;
+public class FluidWrapper : ITemplateEngine
+{
+ private static readonly FluidParser Parser = new();
+
+ public string Render(string source, object model)
+ {
+ var template = Parser.Parse(source);
+ var context = new TemplateContext(model);
+ return template.Render(context);
+ }
+
+ public string Render(Stream stream, object model)
+ {
+ using var reader = new StreamReader(stream);
+ var template = reader.ReadToEnd();
+ return Render(template, model);
+ }
+}
+
diff --git a/testing/Didot.Cli.Testing/Didot.Cli.Testing.csproj b/testing/Didot.Cli.Testing/Didot.Cli.Testing.csproj
index a72f245..74f920a 100644
--- a/testing/Didot.Cli.Testing/Didot.Cli.Testing.csproj
+++ b/testing/Didot.Cli.Testing/Didot.Cli.Testing.csproj
@@ -42,6 +42,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/testing/Didot.Cli.Testing/ProgramTests.cs b/testing/Didot.Cli.Testing/ProgramTests.cs
index 5669275..c5ba201 100644
--- a/testing/Didot.Cli.Testing/ProgramTests.cs
+++ b/testing/Didot.Cli.Testing/ProgramTests.cs
@@ -5,7 +5,10 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Didot.Core.TemplateEngines;
+using HandlebarsDotNet;
using NUnit.Framework;
+using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Didot.Cli.Testing;
@@ -115,6 +118,110 @@ public void Main_MissingTemplate_Failure()
Assert.That(consoleOutput, Does.StartWith("Error parsing arguments."));
}
}
+
+ [Test]
+ public void Main_ForcedEngine_Success()
+ {
+ var args = new string[]
+ {
+ $"-ttemplate/template-01.liquid",
+ $"-sdata/data-01.json",
+ $"-efluid"
+ };
+ Program.Main(args);
+
+ MemoryStream.Position = 0;
+ using (var reader = new StreamReader(MemoryStream))
+ {
+ var consoleOutput = reader.ReadToEnd().Standardize();
+ var expected = File.ReadAllText(Path.Combine("Expectation", $"expectation-01.txt")).Standardize();
+ Assert.That(consoleOutput, Is.EqualTo(expected));
+ }
+ }
+
+ [Test]
+ [TestCase("-x", ':')]
+ [TestCase("-x ", ':')]
+ [TestCase("--Extension=", ':')]
+ public void Main_AddNewExtension_Success(string token, char delimiter)
+ {
+ string extension = "txt";
+ string engineTag = "handlebars";
+ using var source = new StreamReader(Path.Combine("data", $"data-01.json"));
+ Console.SetIn(source);
+
+ var args = new string[]
+ {
+ $"-ttemplate/template-01.{extension}",
+ $"{token}{extension}{delimiter}{engineTag}",
+ $"-pjson"
+ };
+ Program.Main(args);
+
+ MemoryStream.Position = 0;
+ using (var reader = new StreamReader(MemoryStream))
+ {
+ var consoleOutput = reader.ReadToEnd().Standardize();
+ var expected = File.ReadAllText(Path.Combine("Expectation", $"expectation-01.txt")).Standardize();
+ Assert.That(consoleOutput, Is.EqualTo(expected));
+ }
+ }
+
+ [Test]
+ [TestCase("liquid", "fluid")]
+ public void Main_ReplaceExistingExtension_Success(string extension, string engineTag)
+ {
+ using var source = new StreamReader(Path.Combine("data", $"data-01.json"));
+ Console.SetIn(source);
+
+ var args = new string[]
+ {
+ $"-ttemplate/template-01.{extension}",
+ $"-x{extension}:{engineTag}",
+ $"-pjson"
+ };
+ Program.Main(args);
+
+ MemoryStream.Position = 0;
+ using (var reader = new StreamReader(MemoryStream))
+ {
+ var consoleOutput = reader.ReadToEnd().Standardize();
+ var expected = File.ReadAllText(Path.Combine("Expectation", $"expectation-01.txt")).Standardize();
+ Assert.That(consoleOutput, Is.EqualTo(expected));
+ }
+ }
+
+ [Test]
+ [TestCase("-x", ':', ';')]
+ [TestCase("-x ", ':', ';')]
+ [TestCase("--Extension=", ':', ';')]
+ public void Main_AddAndReplaceExtensions_Success(string token, char delimiter, char separator)
+ {
+ var extensions = new string[] { "txt", "liquid" };
+ var engineTags = new string[] { "handlebars", "fluid" };
+ using var source = new StreamReader(Path.Combine("data", $"data-01.json"));
+ Console.SetIn(source);
+
+ var extensionArgs = $"{token}";
+ for (int i = 0; i < extensions.Length; i++)
+ extensionArgs += $"{extensions[i]}{delimiter}{engineTags[i]}{separator}";
+
+ var args = new string[]
+ {
+ $"-ttemplate/template-01.{extensions[0]}",
+ extensionArgs,
+ $"-pjson"
+ };
+ Program.Main(args);
+
+ MemoryStream.Position = 0;
+ using (var reader = new StreamReader(MemoryStream))
+ {
+ var consoleOutput = reader.ReadToEnd().Standardize();
+ var expected = File.ReadAllText(Path.Combine("Expectation", $"expectation-01.txt")).Standardize();
+ Assert.That(consoleOutput, Is.EqualTo(expected));
+ }
+ }
}
public static class StringExtensions
diff --git a/testing/Didot.Cli.Testing/Template/template-01.liquid b/testing/Didot.Cli.Testing/Template/template-01.liquid
index 1993e05..66d6b18 100644
--- a/testing/Didot.Cli.Testing/Template/template-01.liquid
+++ b/testing/Didot.Cli.Testing/Template/template-01.liquid
@@ -1,3 +1,3 @@
{% for employee in model -%}
{{ employee.name.first }} {{ employee.name.last }} is {{ employee.age }} years old.
-{%- endfor %}
+{% endfor %}
diff --git a/testing/Didot.Cli.Testing/Template/template-01.txt b/testing/Didot.Cli.Testing/Template/template-01.txt
new file mode 100644
index 0000000..e02a621
--- /dev/null
+++ b/testing/Didot.Cli.Testing/Template/template-01.txt
@@ -0,0 +1,3 @@
+{{#each model}}
+{{this.name.first}} {{this.name.last}} is {{this.age}} years old.
+{{/each}}
diff --git a/testing/Didot.Core.Testing/TemplateEngines/DotLiquidWrapperTests.cs b/testing/Didot.Core.Testing/TemplateEngines/DotLiquidWrapperTests.cs
index c6079c0..8648a92 100644
--- a/testing/Didot.Core.Testing/TemplateEngines/DotLiquidWrapperTests.cs
+++ b/testing/Didot.Core.Testing/TemplateEngines/DotLiquidWrapperTests.cs
@@ -10,10 +10,13 @@
namespace Didot.Core.Testing.TemplateEngines;
public class DotLiquidWrapperTests
{
+ protected virtual ITemplateEngine GetEngine()
+ => new DotLiquidWrapper();
+
[Test]
public void Render_SingleProperty_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var model = new Dictionary()
{ { "Name", "World"} };
var result = engine.Render("Hello {{model.Name}}", new { model });
@@ -23,7 +26,7 @@ public void Render_SingleProperty_Successful()
[Test]
public void Render_MultiProperty_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var model = new Dictionary()
{ { "Name", "Albert"}, {"Age", 30 } };
var result = engine.Render("Hello {{model.Name}}. You're {{model.Age}} years old.", new { model });
@@ -33,7 +36,7 @@ public void Render_MultiProperty_Successful()
[Test]
public void Render_NestedProperties_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var name = new Dictionary()
{ { "First", "Albert"}, {"Last", "Einstein" } };
var model = new Dictionary()
@@ -45,7 +48,7 @@ public void Render_NestedProperties_Successful()
[Test]
public void Render_ArrayItems_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var albert = new Dictionary()
{ { "Name", "Albert"}, {"Age", 30 } };
var nikola = new Dictionary()
@@ -58,7 +61,7 @@ public void Render_ArrayItems_Successful()
[Test]
public void Render_ArrayLoop_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var albert = new Dictionary()
{ { "Name", "Albert"}, {"Age", 30 } };
var nikola = new Dictionary()
@@ -71,7 +74,7 @@ public void Render_ArrayLoop_Successful()
[Test]
public void Render_Stream_Successful()
{
- var engine = new DotLiquidWrapper();
+ var engine = GetEngine();
var model = new Dictionary()
{ { "Name", "World"} };
using var stream = new MemoryStream(Encoding.UTF8.GetBytes("Hello {{model.Name}}"));
diff --git a/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs b/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
index d07b017..4677fb9 100644
--- a/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
+++ b/testing/Didot.Core.Testing/TemplateEngines/FileBasedTemplateEngineFactoryTests.cs
@@ -19,7 +19,7 @@ public class FileBasedTemplateEngineFactoryTests
public void GetSourceParser_Extension_CorrectParser(string extension, Type expected)
{
var factory = new FileBasedTemplateEngineFactory();
- var parser = factory.GetTemplateEngine(extension);
+ var parser = factory.GetTemplateEngineByExtension(extension);
Assert.That(parser, Is.TypeOf(expected));
}
@@ -28,6 +28,29 @@ public void GetSourceParser_Extension_CorrectParser(string extension, Type expec
public void GetSourceParser_NotSupportedExtension_Exception(string extension)
{
var factory = new FileBasedTemplateEngineFactory();
- Assert.Throws(() => factory.GetTemplateEngine(extension));
+ Assert.Throws(() => factory.GetTemplateEngineByExtension(extension));
+ }
+
+ [Test]
+ public void GetSourceParser_AddedSourceParser_Exception()
+ {
+ var factory = new FileBasedTemplateEngineFactory();
+ factory.AddOrReplaceEngine(".txt", new HandlebarsWrapper());
+ var parser = factory.GetTemplateEngineByExtension(".txt");
+ Assert.That(parser, Is.TypeOf());
+ }
+
+ [Test]
+ [TestCase("scriban", typeof(ScribanWrapper))]
+ [TestCase("dotliquid", typeof(DotLiquidWrapper))]
+ [TestCase("handlebars", typeof(HandlebarsWrapper))]
+ [TestCase("smartformat", typeof(SmartFormatWrapper))]
+ [TestCase("stringtemplate", typeof(StringTemplateWrapper))]
+ [TestCase("fluid", typeof(FluidWrapper))]
+ public void GetSourceParser_ByTag_Successful(string tag, Type expected)
+ {
+ var factory = new FileBasedTemplateEngineFactory();
+ var parser = factory.GetTemplateEngineByTag(tag);
+ Assert.That(parser, Is.TypeOf(expected));
}
}
diff --git a/testing/Didot.Core.Testing/TemplateEngines/FluidWrapperTests.cs b/testing/Didot.Core.Testing/TemplateEngines/FluidWrapperTests.cs
new file mode 100644
index 0000000..c968907
--- /dev/null
+++ b/testing/Didot.Core.Testing/TemplateEngines/FluidWrapperTests.cs
@@ -0,0 +1,15 @@
+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 FluidWrapperTests : DotLiquidWrapperTests
+{
+ protected override ITemplateEngine GetEngine()
+ => new FluidWrapper();
+}