Skip to content

Commit

Permalink
Add JavaScriptEncoder option (#739)
Browse files Browse the repository at this point in the history
Fixes #737
  • Loading branch information
sebastienros authored Dec 30, 2024
1 parent 457e25c commit 8b88d96
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 10 deletions.
32 changes: 28 additions & 4 deletions Fluid.Tests/MiscFiltersTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Fluid.Filters;
using Fluid.Values;
using Newtonsoft.Json.Linq;
using System;
using System.Globalization;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using TimeZoneConverter;
using Xunit;

Expand Down Expand Up @@ -779,6 +780,29 @@ public async Task JsonShouldWriteValuesWithCorrectDataTypeForJObjectInput()
Assert.Equal(expected, result.ToStringValue());
}

[Fact]
public async Task JsonShouldEncodeUnicodeChars()
{
var input = FluidValue.Create("你好,这是一条短信", TemplateOptions.Default);
var result = await MiscFilters.Json(input, new FilterArguments(), new TemplateContext(TemplateOptions.Default));
var expected = @"""\u4F60\u597D\uFF0C\u8FD9\u662F\u4E00\u6761\u77ED\u4FE1""";
Assert.Equal(expected, result.ToStringValue());
}

[Fact]
public async Task JsonShouldUseJsonSerializerOption()
{
var options = new TemplateOptions
{
JavaScriptEncoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

var input = FluidValue.Create("你好,这是一条短信", options);
var result = await MiscFilters.Json(input, new FilterArguments(), new TemplateContext(options));
var expected = @"""你好,这是一条短信""";
Assert.Equal(expected, result.ToStringValue());
}

[Theory]
[InlineData("", "", "", "0")]
[InlineData(123456, "", "", "123456")]
Expand Down
2 changes: 1 addition & 1 deletion Fluid/Filters/MiscFilters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ private static async ValueTask WriteJson(Utf8JsonWriter writer, FluidValue input
}
break;
case FluidValues.String:
writer.WriteStringValue(input.ToStringValue());
writer.WriteStringValue(JsonEncodedText.Encode(input.ToStringValue(), ctx.Options.JavaScriptEncoder));
break;
case FluidValues.Blank:
writer.WriteStringValue(string.Empty);
Expand Down
10 changes: 9 additions & 1 deletion Fluid/TemplateOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Fluid.Values;
using Microsoft.Extensions.FileProviders;
using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;

namespace Fluid
{
Expand All @@ -21,6 +23,8 @@ public class TemplateOptions

public static readonly TemplateOptions Default = new();

private static readonly JavaScriptEncoder DefaultJavaScriptEncoder = JavaScriptEncoder.Default;

/// <summary>
/// Gets ot sets the members than can be accessed in a template.
/// </summary>
Expand Down Expand Up @@ -89,6 +93,11 @@ public class TemplateOptions
/// </summary>
public AssignedDelegate Assigned { get; set; }

/// <summary>
/// Gets or sets the <see cref="JavaScriptEncoder" /> instance used by the <c>json</c> filter.
/// </summary>
public JavaScriptEncoder JavaScriptEncoder { get; set; } = DefaultJavaScriptEncoder;

/// <summary>
/// Gets or sets the default trimming rules.
/// </summary>
Expand All @@ -99,7 +108,6 @@ public class TemplateOptions
/// </summary>
public bool Greedy { get; set; } = true;


public TemplateOptions()
{
Filters.WithArrayFilters()
Expand Down
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,16 +335,35 @@ Not encoded: {{ html | raw }
When using `capture` blocks, the inner content is flagged as
pre-encoded and won't be double-encoded if used in a `{{ }}` tag.

#### Source
### JSON encoding

By default all JSON strings are encoded using the default `JavaScriptEncoder` instance. This can be changed by setting the `TemplateOptions.JavaScriptEncoder` property.

```Liquid
{% capture breaktag %}<br />{% endcapture %}
{{ "你好,这是一条短信" | json" }}
```

#### Result

```html
"\u4F60\u597D\uFF0C\u8FD9\u662F\u4E00\u6761\u77ED\u4FE1"
```

{{ breaktag }}
Using the `JavaScriptEncoder.UnsafeRelaxedJsonEscaping` can be done this way:

```csharp
// This variable should be static and reused for all templates
var options = new TemplateOptions
{
JavaScriptEncoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

var context = new TemplateContext(options);
```

#### Result
```html
<br />
"你好,这是一条短信"
```

<br>
Expand Down

0 comments on commit 8b88d96

Please sign in to comment.