Skip to content

Commit 671fc8b

Browse files
urbanitPiedone
andauthored
Transliterate Liquid Filter (#19009)
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
1 parent 01386f3 commit 671fc8b

18 files changed

Lines changed: 236 additions & 5 deletions

File tree

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
55
</PropertyGroup>
66
<ItemGroup>
7+
<PackageVersion Include="AnyAscii" Version="0.3.2" />
78
<PackageVersion Include="AngleSharp" Version="1.4.0" />
89
<PackageVersion Include="AWSSDK.S3" Version="4.0.19.4" />
910
<PackageVersion Include="AWSSDK.Extensions.NETCore.Setup" Version="4.0.3.28" />

src/OrchardCore.Cms.Web/appsettings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
// "MaxUploadChunkSize": 104857600,
6363
// "TemporaryFileLifetime": "01:00:00"
6464
//},
65+
// See https://docs.orchardcore.net/en/latest/reference/modules/Media/#configuration to configure Media Slugify.
66+
//"OrchardCore_Media_Slugify": {
67+
// "Transliterate": true
68+
//},
6569
// See https://docs.orchardcore.net/en/latest/reference/modules/Media.AmazonS3/#configuration to configure media storage in Amazon S3 Storage.
6670
//"OrchardCore_Media_AmazonS3": {
6771
// "Region": "eu-central-1",

src/OrchardCore.Modules/OrchardCore.Liquid/Filters/SlugifyFilter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ public SlugifyFilter(ISlugService slugService)
1414
}
1515
public ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx)
1616
{
17-
var text = input.ToStringValue();
17+
var transliterateArg = arguments["transliterate"];
18+
var transliterate = transliterateArg.IsNil() || transliterateArg.ToBooleanValue();
1819

19-
return new StringValue(_slugService.Slugify(text));
20+
return new StringValue(_slugService.Slugify(input.ToStringValue(), transliterate));
2021
}
2122
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using AnyAscii;
2+
using Fluid;
3+
using Fluid.Values;
4+
5+
namespace OrchardCore.Liquid.Filters;
6+
7+
public class TransliterateFilter : ILiquidFilter
8+
{
9+
public ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx)
10+
{
11+
var text = input.ToStringValue();
12+
13+
if (string.IsNullOrEmpty(text))
14+
{
15+
return ValueTask.FromResult(input);
16+
}
17+
18+
return ValueTask.FromResult<FluidValue>(StringValue.Create(text.Transliterate()));
19+
}
20+
}

src/OrchardCore.Modules/OrchardCore.Liquid/OrchardCore.Liquid.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
</ItemGroup>
2828

2929
<ItemGroup>
30+
<PackageReference Include="AnyAscii" />
3031
<PackageReference Include="System.IO.Hashing" />
3132
</ItemGroup>
3233

src/OrchardCore.Modules/OrchardCore.Liquid/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public override void ConfigureServices(IServiceCollection services)
7272
.AddLiquidFilter<LocalTimeZoneFilter>("local")
7373
.AddLiquidFilter<UtcTimeZoneFilter>("utc")
7474
.AddLiquidFilter<SlugifyFilter>("slugify")
75+
.AddLiquidFilter<TransliterateFilter>("transliterate")
7576
.AddLiquidFilter<LiquidFilter>("liquid")
7677
.AddLiquidFilter<ContentUrlFilter>("href")
7778
.AddLiquidFilter<AbsoluteUrlFilter>("absolute_url")
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.Extensions.Configuration;
2+
using Microsoft.Extensions.Options;
3+
using OrchardCore.Environment.Shell.Configuration;
4+
5+
namespace OrchardCore.Media.Services;
6+
7+
public sealed class MediaSlugifyOptionsConfiguration : IConfigureOptions<MediaSlugifyOptions>
8+
{
9+
private readonly IShellConfiguration _shellConfiguration;
10+
11+
public MediaSlugifyOptionsConfiguration(IShellConfiguration shellConfiguration)
12+
{
13+
_shellConfiguration = shellConfiguration;
14+
}
15+
16+
public void Configure(MediaSlugifyOptions options)
17+
{
18+
var section = _shellConfiguration.GetSection("OrchardCore_Media_Slugify");
19+
20+
options.Transliterate = section.GetValue(nameof(options.Transliterate), true);
21+
}
22+
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1+
using Microsoft.Extensions.Options;
12
using OrchardCore.Modules.Services;
23

34
namespace OrchardCore.Media.Services;
45

56
public class SlugifyMediaNameNormalizerService : IMediaNameNormalizerService
67
{
78
private readonly ISlugService _slugService;
9+
private readonly MediaSlugifyOptions _options;
810

9-
public SlugifyMediaNameNormalizerService(ISlugService slugService)
11+
public SlugifyMediaNameNormalizerService(
12+
ISlugService slugService,
13+
IOptions<MediaSlugifyOptions> options)
1014
{
1115
_slugService = slugService;
16+
_options = options.Value;
1217
}
1318

1419
public string NormalizeFolderName(string folderName)
1520
{
16-
return _slugService.Slugify(folderName);
21+
return _slugService.Slugify(folderName, _options.Transliterate);
1722
}
1823

1924
public string NormalizeFileName(string fileName)
2025
{
21-
return _slugService.Slugify(Path.GetFileNameWithoutExtension(fileName)) + Path.GetExtension(fileName);
26+
return _slugService.Slugify(Path.GetFileNameWithoutExtension(fileName), _options.Transliterate) + Path.GetExtension(fileName);
2227
}
2328
}

src/OrchardCore.Modules/OrchardCore.Media/Startup.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ public sealed class MediaSlugifyStartup : StartupBase
246246
{
247247
public override void ConfigureServices(IServiceCollection services)
248248
{
249+
services.AddTransient<IConfigureOptions<MediaSlugifyOptions>, MediaSlugifyOptionsConfiguration>();
250+
249251
// Media Name Normalizer
250252
services.AddScoped<IMediaNameNormalizerService, SlugifyMediaNameNormalizerService>();
251253
}

src/OrchardCore/OrchardCore.Abstractions/Modules/Services/ISlugService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ public interface ISlugService
99
/// <returns>The slug created from the input text.</returns>
1010
string Slugify(string text);
1111

12+
/// <summary>
13+
/// Transforms specified text to the form suitable for URL slugs,
14+
/// optionally transliterating non-Latin characters to their ASCII equivalents first.
15+
/// </summary>
16+
/// <param name="text">The text to transform.</param>
17+
/// <param name="transliterate">Whether to transliterate non-Latin characters before slugifying.</param>
18+
/// <returns>The slug created from the input text.</returns>
19+
string Slugify(string text, bool transliterate);
20+
1221
/// <summary>
1322
/// Transforms specified text to a custom form generally not suitable for URL slugs.
1423
/// Allows you to use a specified separator char.

0 commit comments

Comments
 (0)