Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Renderers/FluentEmail.Liquid/FluentEmail.Liquid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Fluid.Core" Version="1.0.0" />
<PackageReference Include="Fluid.Core" Version="2.0.13" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
</ItemGroup>

Expand Down
17 changes: 0 additions & 17 deletions src/Renderers/FluentEmail.Liquid/FluidViewTemplate.cs

This file was deleted.

84 changes: 84 additions & 0 deletions src/Renderers/FluentEmail.Liquid/LiquidParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Fluid;
using Fluid.Ast;

public class LiquidParser : FluidParser
{
public LiquidParser()
{
RegisterExpressionTag("layout", OnRegisterLayoutTag);
RegisterEmptyTag("renderbody", OnRegisterRenderBodyTag);
RegisterIdentifierBlock("section", OnRegisterSectionBlock);
RegisterIdentifierTag("rendersection", OnRegisterSectionTag);
}

private async ValueTask<Completion> OnRegisterLayoutTag(Expression expression, TextWriter writer, TextEncoder encoder, TemplateContext context)
{
const string viewExtension = ".liquid";

var relativeLayoutPath = (await expression.EvaluateAsync(context)).ToStringValue();

if (!relativeLayoutPath.EndsWith(viewExtension, StringComparison.OrdinalIgnoreCase))
{
relativeLayoutPath += viewExtension;
}

context.AmbientValues["Layout"] = relativeLayoutPath;

return Completion.Normal;
}

private async ValueTask<Completion> OnRegisterRenderBodyTag(TextWriter writer, TextEncoder encoder, TemplateContext context)
{
static void ThrowParseException()
{
throw new ParseException("Could not render body, Layouts can't be evaluated directly.");
}

if (context.AmbientValues.TryGetValue("Body", out var body))
{
await writer.WriteAsync((string)body);
}
else
{
ThrowParseException();
}

return Completion.Normal;
}

private ValueTask<Completion> OnRegisterSectionBlock(string sectionName, IReadOnlyList<Statement> statements, TextWriter writer, TextEncoder encoder, TemplateContext context)
{
if (context.AmbientValues.TryGetValue("Sections", out var sections))
{
var dictionary = (Dictionary<string, List<Statement>>) sections;

dictionary[sectionName] = statements.ToList();
}

return new ValueTask<Completion>(Completion.Normal);
}

private async ValueTask<Completion> OnRegisterSectionTag(string sectionName, TextWriter writer, TextEncoder encoder, TemplateContext context)
{
if (context.AmbientValues.TryGetValue("Sections", out var sections))
{
var dictionary = (Dictionary<string, List<Statement>>) sections;

if (dictionary.TryGetValue(sectionName, out var section))
{
foreach(var statement in section)
{
await statement.WriteToAsync(writer, encoder, context);
}
}
}

return Completion.Normal;
}
}
17 changes: 9 additions & 8 deletions src/Renderers/FluentEmail.Liquid/LiquidRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ namespace FluentEmail.Liquid
{
public class LiquidRenderer : ITemplateRenderer
{
private static readonly Func<IFluidTemplate> FluidTemplateFactory = () => new FluidViewTemplate();

private readonly IOptions<LiquidRendererOptions> _options;
private readonly LiquidParser _parser;

public LiquidRenderer(IOptions<LiquidRendererOptions> options)
{
_options = options;
_parser = new LiquidParser();
}

public string Parse<T>(string template, T model, bool isHtml = true)
Expand All @@ -42,9 +42,10 @@ public async Task<string> ParseAsync<T>(string template, T model, bool isHtml =
["FileProvider"] = fileProvider,
["Sections"] = new Dictionary<string, List<Statement>>()
},
ParserFactory = FluidViewTemplate.Factory,
TemplateFactory = FluidTemplateFactory,
FileProvider = fileProvider
Options =
{
FileProvider = fileProvider
}
};

rendererOptions.ConfigureTemplateContext?.Invoke(context, model!);
Expand All @@ -63,7 +64,7 @@ public async Task<string> ParseAsync<T>(string template, T model, bool isHtml =
return body;
}

private static FluidViewTemplate ParseLiquidFile(
private IFluidTemplate ParseLiquidFile(
string path,
IFileProvider? fileProvider)
{
Expand All @@ -85,9 +86,9 @@ static void ThrowMissingFileProviderException()
return ParseTemplate(sr.ReadToEnd());
}

private static FluidViewTemplate ParseTemplate(string content)
private IFluidTemplate ParseTemplate(string content)
{
if (!FluidViewTemplate.TryParse(content, out var template, out var errors))
if (!_parser.TryParse(content, out var template, out var errors))
{
throw new Exception(string.Join(Environment.NewLine, errors));
}
Expand Down
28 changes: 0 additions & 28 deletions src/Renderers/FluentEmail.Liquid/Tags/LayoutTag.cs

This file was deleted.

26 changes: 0 additions & 26 deletions src/Renderers/FluentEmail.Liquid/Tags/RegisterSectionBlock.cs

This file was deleted.

31 changes: 0 additions & 31 deletions src/Renderers/FluentEmail.Liquid/Tags/RenderBodyTag.cs

This file was deleted.

30 changes: 0 additions & 30 deletions src/Renderers/FluentEmail.Liquid/Tags/RenderSectionTag.cs

This file was deleted.

10 changes: 3 additions & 7 deletions test/FluentEmail.Liquid.Tests/LiquidTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class LiquidTests
public void SetUp()
{
// default to have no file provider, only required when layout files are in use
SetupRenderer(null);
SetupRenderer();
}

private static void SetupRenderer(
Expand Down Expand Up @@ -51,7 +51,6 @@ public void Model_With_List_Template_Matches()
Assert.AreEqual("sup LUKE here is a list 123", email.Data.Body);
}


[Test]
public void Custom_Context_Values()
{
Expand Down Expand Up @@ -155,8 +154,7 @@ public void Should_be_able_to_use_project_layout()
{
SetupRenderer(new PhysicalFileProvider(Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory!.FullName, "EmailTemplates")));

const string template = @"
{% layout '_layout.liquid' %}
const string template = @"{% layout '_layout.liquid' %}
sup {{ Name }} here is a list {% for i in Numbers %}{{ i }}{% endfor %}";

var email = new Email(FromEmail)
Expand All @@ -167,14 +165,12 @@ public void Should_be_able_to_use_project_layout()
Assert.AreEqual($"<h1>Hello!</h1>{Environment.NewLine}<div>{Environment.NewLine}sup LUKE here is a list 123</div>", email.Data.Body);
}


[Test]
public void Should_be_able_to_use_embedded_layout()
{
SetupRenderer(new EmbeddedFileProvider(typeof(LiquidTests).Assembly, "FluentEmail.Liquid.Tests.EmailTemplates"));

const string template = @"
{% layout '_embedded.liquid' %}
const string template = @"{% layout '_embedded.liquid' %}
sup {{ Name }} here is a list {% for i in Numbers %}{{ i }}{% endfor %}";

var email = new Email(FromEmail)
Expand Down