Add support for custom liquid tags

This commit is contained in:
Sipke Schoorstra 2021-03-26 17:26:44 +01:00
parent 64e2b74092
commit c4f8eafba7
5 changed files with 74 additions and 4 deletions

View file

@ -1,3 +1,4 @@
using System;
using Elsa.Expressions;
using Elsa.Scripting.Liquid.Filters;
using Elsa.Scripting.Liquid.Options;
@ -15,7 +16,9 @@ namespace Elsa.Scripting.Liquid.Extensions
.AddMemoryCache()
.AddNotificationHandlers(typeof(LiquidServiceCollectionExtensions))
.AddScoped<ILiquidTemplateManager, LiquidTemplateManager>()
.AddLiquidFilter<JsonFilter>("json");
.AddSingleton<LiquidParser>()
.AddLiquidFilter<JsonFilter>("json")
.AddLiquidFilter<Base64Filter>("base64");
}
public static IServiceCollection AddLiquidFilter<T>(this IServiceCollection services, string name) where T : class, ILiquidFilter
@ -24,5 +27,11 @@ namespace Elsa.Scripting.Liquid.Extensions
services.AddScoped<T>();
return services;
}
public static IServiceCollection RegisterLiquidTag(this IServiceCollection services, Action<LiquidParser> configure)
{
services.Configure<LiquidOptions>(options => options.ParserConfiguration.Add(configure));
return services;
}
}
}

View file

@ -0,0 +1,42 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Elsa.Scripting.Liquid.Services;
using Fluid;
using Fluid.Values;
using Newtonsoft.Json;
namespace Elsa.Scripting.Liquid.Filters
{
public class Base64Filter : ILiquidFilter
{
public ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, TemplateContext context)
{
var text = InputToString(input);
if (text == null)
return new ValueTask<FluidValue>(NilValue.Instance);
var bytes = Encoding.UTF8.GetBytes(text);
var base64 = Convert.ToBase64String(bytes);
return new ValueTask<FluidValue>(new StringValue(base64));
}
private string? InputToString(FluidValue input)
{
return input.Type switch
{
FluidValues.Array => JsonConvert.SerializeObject(input.Enumerate().Select(o => o.ToObjectValue())),
FluidValues.Boolean => input.ToBooleanValue().ToString(),
FluidValues.Nil => null,
FluidValues.Number => input.ToNumberValue().ToString(CultureInfo.InvariantCulture),
FluidValues.DateTime or FluidValues.Dictionary or FluidValues.Object => JsonConvert.SerializeObject(input.ToObjectValue()),
FluidValues.String => input.ToStringValue(),
_ => throw new ArgumentOutOfRangeException(nameof(input), "Unrecognized FluidValue")
};
}
}
}

View file

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using Elsa.Scripting.Liquid.Services;
namespace Elsa.Scripting.Liquid.Options
{
public class LiquidOptions
{
public Dictionary<string, Type> FilterRegistrations { get; } = new Dictionary<string, Type>();
public Dictionary<string, Type> FilterRegistrations { get; } = new();
public IList<Action<LiquidParser>> ParserConfiguration { get; } = new List<Action<LiquidParser>>();
}
}

View file

@ -0,0 +1,15 @@
using Elsa.Scripting.Liquid.Options;
using Fluid;
using Microsoft.Extensions.Options;
namespace Elsa.Scripting.Liquid.Services
{
public class LiquidParser : FluidParser
{
public LiquidParser(IOptions<LiquidOptions> options)
{
foreach (var configuration in options.Value.ParserConfiguration)
configuration(this);
}
}
}

View file

@ -11,12 +11,14 @@ namespace Elsa.Scripting.Liquid.Services
{
public class LiquidTemplateManager : ILiquidTemplateManager
{
private readonly LiquidParser _parser;
private readonly IMemoryCache _memoryCache;
private readonly IServiceProvider _serviceProvider;
private readonly LiquidOptions _options;
public LiquidTemplateManager(IMemoryCache memoryCache, IOptions<LiquidOptions> options, IServiceProvider serviceProvider)
public LiquidTemplateManager(LiquidParser parser, IMemoryCache memoryCache, IOptions<LiquidOptions> options, IServiceProvider serviceProvider)
{
_parser = parser;
_memoryCache = memoryCache;
_serviceProvider = serviceProvider;
_options = options.Value;
@ -52,6 +54,6 @@ namespace Elsa.Scripting.Liquid.Services
public bool Validate(string template, out string error) => TryParse(template, out _, out error);
private static bool TryParse(string template, out IFluidTemplate result, out string error) => new FluidParser().TryParse(template, out result, out error);
private bool TryParse(string template, out IFluidTemplate result, out string error) => _parser.TryParse(template, out result, out error);
}
}