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
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