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
50 changes: 50 additions & 0 deletions Fluid/FluidTemplateExtensions.String.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Fluid.Utils;
using System.Runtime.CompilerServices;
using System.Text.Encodings.Web;

namespace Fluid
{
public static partial class FluidTemplateExtensions
{
/// <summary>
/// Renders the specified Fluid template asynchronously using a new TemplateContext.
/// </summary>
/// <param name="template">The Fluid template to render.</param>
/// <returns>A ValueTask that represents the asynchronous rendering operation. The task result contains the rendered template as a string.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueTask<string> RenderAsync(this IFluidTemplate template)
{
return RenderAsync(template, new TemplateContext());
}

/// <summary>
/// Renders the specified Fluid template asynchronously using the provided context and a default text encoder.
/// </summary>
/// <param name="template">The Fluid template to render.</param>
/// <param name="context">The context to use for rendering the template.</param>
/// <returns>A ValueTask that represents the asynchronous rendering operation. The task result contains the rendered template as a string.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueTask<string> RenderAsync(this IFluidTemplate template, TemplateContext context)
{
return RenderAsync(template, context, NullEncoder.Default);
}

/// <summary>
/// Renders the specified Fluid template asynchronously using the provided context, encoder, and isolation settings.
/// </summary>
/// <param name="template">The Fluid template to render.</param>
/// <param name="context">The context to use for rendering the template.</param>
/// <param name="encoder">The text encoder to use for encoding the output.</param>
/// <param name="isolateContext">A boolean value indicating whether to isolate the context during rendering.</param>
/// <returns>A ValueTask that represents the asynchronous rendering operation. The task result contains the rendered template as a string.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async ValueTask<string> RenderAsync(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, bool isolateContext = true)
{
using var sb = StringBuilderPool.GetInstance();
using var writer = new StringWriter(sb.Builder);

await RenderAsync(template, writer, context, encoder, isolateContext);
return sb.ToString();
}
}
}
64 changes: 64 additions & 0 deletions Fluid/FluidTemplateExtensions.Sync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Runtime.CompilerServices;
using System.Text.Encodings.Web;

namespace Fluid
{
public static partial class FluidTemplateExtensions
{
/// <summary>
/// Renders the template to a string.
/// </summary>
/// <param name="template">The template to render.</param>
/// <returns>The rendered template as a string.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template)
{
return Render(template, new TemplateContext());
}

/// <summary>
/// Renders the template to a string using the specified context.
/// </summary>
/// <param name="template">The template to render.</param>
/// <param name="context">The context to use for rendering.</param>
/// <returns>The rendered template as a string.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template, TemplateContext context)
{
return Render(template, context, NullEncoder.Default);
}

/// <summary>
/// Renders the template to the specified text writer using the specified context and text encoder.
/// </summary>
/// <param name="template">The template to render.</param>
/// <param name="context">The context to use for rendering.</param>
/// <param name="encoder">The text encoder to use for rendering.</param>
/// <param name="isolateContext">A boolean value indicating whether to isolate the context during rendering.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, bool isolateContext = true)
{
var task = RenderAsync(template, context, encoder, isolateContext);
return task.IsCompletedSuccessfully ? task.Result : task.AsTask().GetAwaiter().GetResult();
}

/// <summary>
/// Renders the template to the specified text writer using the specified context and text encoder.
/// This method is obsolete and will be removed in a future version.
/// </summary>
/// <param name="template">The template to render.</param>
/// <param name="context">The context to use for rendering.</param>
/// <param name="encoder">The text encoder to use for rendering.</param>
/// <param name="writer">The text writer to write the rendered template to.</param>
[Obsolete("Use Render(this IFluidTemplate template, TextWriter writer, TemplateContext context, TextEncoder encoder) instead. This method will be removed in a future version.")]
public static void Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, TextWriter writer)
{
var task = RenderAsync(template, writer, context, encoder);

if (!task.IsCompletedSuccessfully)
{
task.AsTask().GetAwaiter().GetResult();
}
}
}
}
77 changes: 34 additions & 43 deletions Fluid/FluidTemplateExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,53 @@
using Fluid.Utils;
using System.Runtime.CompilerServices;
using System.Text.Encodings.Web;

namespace Fluid
{
public static class FluidTemplateExtensions
public static partial class FluidTemplateExtensions
{
/// <summary>
/// Renders a Fluid template asynchronously to a specified text writer. It uses a default template context for
/// rendering.
/// </summary>
/// <param name="template">Specifies the fluid template to be rendered.</param>
/// <param name="textWriter">Defines the output destination for the rendered content.</param>
/// <returns>Returns a ValueTask representing the asynchronous rendering operation.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueTask<string> RenderAsync(this IFluidTemplate template, TemplateContext context)
public static ValueTask RenderAsync(this IFluidTemplate template, TextWriter textWriter)
{
return template.RenderAsync(context, NullEncoder.Default);
return template.RenderAsync(textWriter, new TemplateContext());
}

/// <summary>
/// Renders a Fluid template asynchronously to a specified text writer using a default encoder.
/// </summary>
/// <param name="template">Represents the template to be rendered.</param>
/// <param name="textWriter">Used to write the rendered output of the template.</param>
/// <param name="context">Provides the context for rendering the template.</param>
/// <returns>Returns a ValueTask representing the asynchronous operation.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder)
public static ValueTask RenderAsync(this IFluidTemplate template, TextWriter textWriter, TemplateContext context)
{
var task = template.RenderAsync(context, encoder);
return task.IsCompletedSuccessfully ? task.Result : task.AsTask().GetAwaiter().GetResult();
return template.RenderAsync(textWriter, context, NullEncoder.Default);
}

/// <summary>
/// Renders a Fluid template asynchronously to a specified text writer using a given context and encoder.
/// </summary>
/// <param name="template">Specifies the fluid template to be rendered.</param>
/// <param name="textWriter">Defines the output destination for the rendered content.</param>
/// <param name="context">Provides the context in which the template is evaluated.</param>
/// <param name="encoder">Handles the encoding of the output content.</param>
/// <param name="isolateContext">Indicates whether to evaluate the template in a separate context scope.</param>
/// <returns>Returns a ValueTask representing the asynchronous operation.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, TextWriter writer)
public static async ValueTask RenderAsync(this IFluidTemplate template, TextWriter textWriter, TemplateContext context, TextEncoder encoder, bool isolateContext = true)
{
var task = template.RenderAsync(writer, encoder, context);
if (!task.IsCompletedSuccessfully)
if (textWriter == null)
{
task.AsTask().GetAwaiter().GetResult();
ExceptionHelper.ThrowArgumentNullException(nameof(textWriter));
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async ValueTask<string> RenderAsync(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, bool isolateContext = true)
{
if (context == null)
{
ExceptionHelper.ThrowArgumentNullException(nameof(context));
Expand All @@ -42,9 +58,6 @@ public static async ValueTask<string> RenderAsync(this IFluidTemplate template,
ExceptionHelper.ThrowArgumentNullException(nameof(template));
}

var sb = StringBuilderPool.GetInstance();
var writer = new StringWriter(sb.Builder);

// A template is evaluated in a child scope such that the provided TemplateContext is immutable
if (isolateContext)
{
Expand All @@ -53,41 +66,19 @@ public static async ValueTask<string> RenderAsync(this IFluidTemplate template,

try
{
await template.RenderAsync(writer, encoder, context);
await template.RenderAsync(textWriter, encoder, context);

writer.Flush();
return sb.ToString();
textWriter.Flush();
}
finally
{
sb.Dispose();
writer.Dispose();
textWriter.Dispose();

if (isolateContext)
{
context.ReleaseScope();
}
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template, TemplateContext context)
{
var task = template.RenderAsync(context);
return task.IsCompletedSuccessfully ? task.Result : task.AsTask().GetAwaiter().GetResult();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ValueTask<string> RenderAsync(this IFluidTemplate template)
{
return template.RenderAsync(new TemplateContext());
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Render(this IFluidTemplate template)
{
var task = template.RenderAsync();
return task.IsCompletedSuccessfully ? task.Result : task.AsTask().GetAwaiter().GetResult();
}
}
}