Skip to content

Commit

Permalink
Added StringComparer property to TemplateContext (#681)
Browse files Browse the repository at this point in the history
Co-authored-by: Hisham Bin Ateya <[email protected]>
Co-authored-by: Sebastien Ros <[email protected]>
  • Loading branch information
3 people authored Sep 30, 2024
1 parent e31857a commit f5af4c8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 10 deletions.
19 changes: 19 additions & 0 deletions Fluid.Tests/TemplateContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,25 @@ public async Task ShouldNotReleaseScopeAsynchronously()

Assert.Equal("101", output);
}

[Fact]
public void ShouldUseCustomStringComparer()
{
var context = new TemplateContext(StringComparer.OrdinalIgnoreCase);
context.SetValue("PageState", "insert");

Assert.Equal("insert", context.GetValue("pageState").ToStringValue());
}

[Fact]
public void ShouldUseTemplateOptionsStringComparer()
{
var options = new TemplateOptions { ModelNamesComparer = StringComparer.OrdinalIgnoreCase };
var context = new TemplateContext(options);
context.SetValue("PageState", "insert");

Assert.Equal("insert", context.GetValue("pageState").ToStringValue());
}

private class TestClass
{
Expand Down
11 changes: 5 additions & 6 deletions Fluid/Scope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ public sealed class Scope
private Dictionary<string, FluidValue> _properties;
private readonly bool _forLoopScope;

public Scope()
public Scope() : this(null)
{
Parent = null;
}

public Scope(Scope parent)
Expand All @@ -23,12 +22,12 @@ public Scope(Scope parent, bool forLoopScope)
if (forLoopScope && parent == null) ExceptionHelper.ThrowArgumentNullException(nameof(parent));

Parent = parent;

// A ForLoop scope reads and writes its values in the parent scope.
// Internal accessors to the inner properties grant access to the local properties.
_forLoopScope = forLoopScope;

_properties = new Dictionary<string, FluidValue>();
// ForLoop scopes are ordinal since the properties are keywords: "forloop"
_properties = new Dictionary<string, FluidValue>(StringComparer.OrdinalIgnoreCase);
}

/// <summary>
Expand Down Expand Up @@ -115,7 +114,7 @@ public void SetValue(string name, FluidValue value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetOwnValue(string name, FluidValue value)
{
_properties ??= new Dictionary<string, FluidValue>();
_properties ??= new Dictionary<string, FluidValue>(Parent?._properties?.Comparer ?? TemplateOptions.Default.ModelNamesComparer);
_properties[name] = value ?? NilValue.Instance;
}

Expand All @@ -138,4 +137,4 @@ public void CopyTo(Scope scope)
}
}
}
}
}
16 changes: 12 additions & 4 deletions Fluid/TemplateContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public TemplateContext(object model, TemplateOptions options, bool allowModelMem
/// Initializes a new instance of <see cref="TemplateContext"/> with the specified <see cref="TemplateOptions"/>.
/// </summary>
/// <param name="options">The template options.</param>
public TemplateContext(TemplateOptions options)
/// <param name="modelNamesComparer">An optional <see cref="StringComparer"/> instance used when comparing model names.</param>
public TemplateContext(TemplateOptions options, StringComparer modelNamesComparer = null)
{
Options = options;
LocalScope = new Scope(options.Scope);
Expand All @@ -54,14 +55,16 @@ public TemplateContext(TemplateOptions options)
Captured = options.Captured;
Now = options.Now;
MaxSteps = options.MaxSteps;
ModelNamesComparer = modelNamesComparer ?? options.ModelNamesComparer;
}

/// <summary>
/// Initializes a new instance of <see cref="TemplateContext"/> wih a model and option regiter its properties.
/// Initializes a new instance of <see cref="TemplateContext"/> wih a model and option register its properties.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="allowModelMembers">Whether the members of the model can be accessed by default.</param>
public TemplateContext(object model, bool allowModelMembers = true) : this()
/// <param name="modelNamesComparer">An optional <see cref="StringComparer"/> instance used when comparing model names.</param>
public TemplateContext(object model, bool allowModelMembers = true, StringComparer modelNamesComparer = null) : this(TemplateOptions.Default, modelNamesComparer)
{
if (model == null)
{
Expand Down Expand Up @@ -89,6 +92,11 @@ public TemplateContext(object model, bool allowModelMembers = true) : this()
/// </summary>
public int MaxSteps { get; set; } = TemplateOptions.Default.MaxSteps;

/// <summary>
/// Gets <see cref="StringComparer"/> used when comparing model names.
/// </summary>
public StringComparer ModelNamesComparer { get; private set; }

/// <summary>
/// Gets or sets the <see cref="CultureInfo"/> instance used to render locale values like dates and numbers.
/// </summary>
Expand Down Expand Up @@ -136,7 +144,7 @@ public void IncrementSteps()

/// <summary>
/// Gets or sets a model object that is used to resolve properties in a template. This object is used if local and
/// global scopes are unsuccessfull.
/// global scopes are unsuccessful.
/// </summary>
public FluidValue Model { get; }

Expand Down
8 changes: 8 additions & 0 deletions Fluid/TemplateOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public class TemplateOptions
/// </summary>
public int MaxSteps { get; set; }

/// <summary>
/// Gets or sets the <see cref="StringComparer"/> to use when comparing model names.
/// </summary>
/// <value>
/// Default value is <see cref="StringComparer.OrdinalIgnoreCase"/>
/// </value>
public StringComparer ModelNamesComparer { get; set; } = StringComparer.OrdinalIgnoreCase;

/// <summary>
/// Gets or sets the <see cref="CultureInfo"/> instance used to render locale values like dates and numbers.
/// </summary>
Expand Down

0 comments on commit f5af4c8

Please sign in to comment.