Skip to content

Commit

Permalink
Cleanup, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed Feb 1, 2025
1 parent e086c34 commit 0632fc6
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 61 deletions.
83 changes: 75 additions & 8 deletions src/RazorBlade.Library.Tests/RazorTemplateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public void should_write_encoded_content()
}

[Test]
[SuppressMessage("ReSharper", "MethodHasAsyncOverload")]
#if NETFRAMEWORK
[Timeout(10_000)]
#endif
Expand Down Expand Up @@ -207,7 +208,60 @@ public void should_execute_templated_delegate()
template.Render().ShouldEqual("<b>Bold text</b> - <b>Other bold text</b>");
}

private class Template(Func<Template, Task> executeAction) : RazorTemplate
[Test]
public void should_write_directly_to_output_with_no_layout()
{
var output = new StringWriter();

var template = new Template(
t =>
{
t.WriteLiteral("foo");
output.ToString().ShouldEqual("foo");
return Task.CompletedTask;
},
() => null
);

template.Render(output);
output.ToString().ShouldEqual("foo");
}

[Test]
public void should_buffer_output_when_using_layout()
{
var output = new StringWriter();

var template = new Template(
t =>
{
t.WriteLiteral("foo");
output.ToString().ShouldBeEmpty();
return Task.CompletedTask;
},
() => new EmptyLayout()
);

template.Render(output);
output.ToString().ShouldEqual("foo");
}

private abstract class BaseRazorTemplate : RazorTemplate
{
protected internal override void BeginWriteAttribute(string name, string prefix, int prefixOffset, string suffix, int suffixOffset, int attributeValuesCount)
{
}

protected internal override void WriteAttributeValue(string prefix, int prefixOffset, object? value, int valueOffset, int valueLength, bool isLiteral)
{
}

protected internal override void EndWriteAttribute()
{
}
}

private class Template(Func<Template, Task> executeAction, Func<IRazorLayout?>? createLayout = null) : BaseRazorTemplate
{
public Template(Action<Template> executeAction)
: this(t =>
Expand All @@ -224,24 +278,37 @@ protected internal override async Task ExecuteAsync()
await base.ExecuteAsync();
}

private protected override IRazorLayout? CreateLayoutInternal()
=> createLayout?.Invoke();

protected internal override void Write(object? value)
{
if (value is IEncodedContent encodedContent)
encodedContent.WriteTo(Output);
else
WriteLiteral(value?.ToString());
}
}

protected internal override void BeginWriteAttribute(string name, string prefix, int prefixOffset, string suffix, int suffixOffset, int attributeValuesCount)
{
}
private class EmptyLayout : BaseRazorTemplate, IRazorLayout
{
public Task<IRazorExecutionResult> ExecuteLayoutAsync(IRazorExecutionResult input)
=> Task.FromResult<IRazorExecutionResult>(new Result(input.Body));

protected internal override void WriteAttributeValue(string prefix, int prefixOffset, object? value, int valueOffset, int valueLength, bool isLiteral)
{
}
protected internal override void Write(object? value)
=> throw new InvalidOperationException();

protected internal override void EndWriteAttribute()
private class Result(IEncodedContent body) : IRazorExecutionResult
{
public IEncodedContent Body => body;
public IRazorLayout? Layout => null;
public CancellationToken CancellationToken => CancellationToken.None;

public bool IsSectionDefined(string name)
=> false;

public Task<IEncodedContent?> RenderSectionAsync(string name)
=> Task.FromResult<IEncodedContent?>(null);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/RazorBlade.Library/HtmlHelper.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using JetBrains.Annotations;

namespace RazorBlade;

// ReSharper disable once RedundantDisableWarningComment
#pragma warning disable CA1822

/// <summary>
/// Utilities for HTML Razor templates.
/// </summary>
[SuppressMessage("ReSharper", "MemberCanBeMadeStatic.Global")]
public sealed class HtmlHelper
{
#if NET8_0_OR_GREATER
Expand All @@ -26,13 +24,15 @@ public sealed class HtmlHelper
/// Returns markup that is not HTML encoded.
/// </summary>
/// <param name="value">The HTML markup.</param>
[PublicAPI]
public HtmlString Raw(object? value)
=> new(value?.ToString());

/// <summary>
/// HTML-encodes the provided value.
/// </summary>
/// <param name="value">Value to HTML-encode.</param>
[PublicAPI]
public string Encode(object? value)
{
var valueString = value?.ToString();
Expand Down
7 changes: 7 additions & 0 deletions src/RazorBlade.Library/HtmlLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace RazorBlade;

Expand Down Expand Up @@ -80,6 +81,7 @@ private protected override Task<IRazorExecutionResult> ExecuteAsyncCore(TextWrit
/// <summary>
/// Returns the inner page body.
/// </summary>
[PublicAPI]
protected internal IEncodedContent RenderBody()
=> GetLayoutInput().Body;

Expand All @@ -88,6 +90,7 @@ protected internal IEncodedContent RenderBody()
/// </summary>
/// <param name="name">The section name.</param>
/// <returns>The content to write to the output.</returns>
[PublicAPI]
protected internal IEncodedContent RenderSection(string name)
=> RenderSection(name, true);

Expand All @@ -97,6 +100,7 @@ protected internal IEncodedContent RenderSection(string name)
/// <param name="name">The section name.</param>
/// <param name="required">Whether the section is required.</param>
/// <returns>The content to write to the output.</returns>
[PublicAPI]
protected internal IEncodedContent RenderSection(string name, bool required)
{
var renderTask = RenderSectionAsync(name, required);
Expand All @@ -111,6 +115,7 @@ protected internal IEncodedContent RenderSection(string name, bool required)
/// </summary>
/// <param name="name">The section name.</param>
/// <returns>The content to write to the output.</returns>
[PublicAPI]
protected internal Task<IEncodedContent> RenderSectionAsync(string name)
=> RenderSectionAsync(name, true);

Expand All @@ -120,6 +125,7 @@ protected internal Task<IEncodedContent> RenderSectionAsync(string name)
/// <param name="name">The section name.</param>
/// <param name="required">Whether the section is required.</param>
/// <returns>The content to write to the output.</returns>
[PublicAPI]
protected internal async Task<IEncodedContent> RenderSectionAsync(string name, bool required)
{
var result = await GetLayoutInput().RenderSectionAsync(name).ConfigureAwait(false);
Expand All @@ -137,6 +143,7 @@ protected internal async Task<IEncodedContent> RenderSectionAsync(string name, b
/// Indicates if a given section is defined.
/// </summary>
/// <param name="name">The section name.</param>
[PublicAPI]
protected internal bool IsSectionDefined(string name)
=> GetLayoutInput().IsSectionDefined(name);

Expand Down
2 changes: 1 addition & 1 deletion src/RazorBlade.Library/HtmlTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public abstract class HtmlTemplate<TModel> : HtmlTemplate
/// <summary>
/// The model for the template.
/// </summary>
[UsedImplicitly]
[PublicAPI]
public TModel Model { get; }

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/RazorBlade.Library/PlainTextTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public abstract class PlainTextTemplate<TModel> : PlainTextTemplate
/// <summary>
/// The model for the template.
/// </summary>
[UsedImplicitly]
[PublicAPI]
public TModel Model { get; }

/// <summary>
Expand Down
Loading

0 comments on commit 0632fc6

Please sign in to comment.