public static void TestTextEncoder() { var values = new object[] { 2, '\n', TextEncodingEscaper.DefaultSeparator, long.MaxValue, int.MinValue, double.MaxValue / 2, -double.Epsilon, DateTime.Now, "\ne#$", "\t" }; foreach (var value in values) { foreach (var type in new[] { IoType.Key, IoType.Value }) { var stream = new StreamContext(); var encoder = new TextEncoder(stream.writer); var decoder = new TextDecoder(stream.reader); Action f = () => encoder.WriteChar(TextEncodingEscaper.DefaultSeparator, IoType.Raw); TestEncoderHelper(value, encoder, decoder, stream, type, f); } } }
public void TestTextEncoder() { TextEncoder encoder = new TextEncoder(); Assert.AreEqual("0.0", encoder.Convert(0)); Assert.AreEqual("100.0", encoder.Convert(100)); Assert.AreEqual("1.1", encoder.Convert(1.12f)); Assert.AreEqual("-1", encoder.Convert(null)); }
public static async ValueTask <Completion> WriteToAsync(ValueTuple <Expression, Expression> arguments, TextWriter writer, TextEncoder encoder, TemplateContext context) { var objectValue = (await arguments.Item1.EvaluateAsync(context)).ToObjectValue(); if (objectValue is IShape shape) { var classes = await arguments.Item2.EvaluateAsync(context); if (classes.Type == FluidValues.String) { var values = classes.ToStringValue().Split(' ', StringSplitOptions.RemoveEmptyEntries); foreach (var value in values) { shape.Classes.Add(value); } } else if (classes.Type == FluidValues.Array) { foreach (var value in classes.Enumerate()) { shape.Classes.Add(value.ToStringValue()); } } } return(Completion.Normal); }
public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context, Expression expression, FilterArgument[] args) { var objectValue = (await expression.EvaluateAsync(context)).ToObjectValue() as dynamic; if (objectValue is Shape shape) { var arguments = (FilterArguments)(await new ArgumentsExpression(args).EvaluateAsync(context)).ToObjectValue(); if (shape.Metadata.Type == "PagerSlim") { foreach (var name in arguments.Names) { var argument = arguments[name]; var propertyName = name.ToPascalCaseUnderscore(); if (_properties.Contains(propertyName)) { objectValue[propertyName] = argument.ToStringValue(); } } } if (shape.Metadata.Type == "PagerSlim" || shape.Metadata.Type == "Pager") { if (arguments.Names.Contains("item_classes")) { var classes = arguments["item_classes"]; if (classes.Type == FluidValues.String) { var values = classes.ToStringValue().Split(' ', StringSplitOptions.RemoveEmptyEntries); foreach (var value in values) { objectValue.ItemClasses.Add(value); } } else if (classes.Type == FluidValues.Array) { foreach (var value in classes.Enumerate()) { objectValue.ItemClasses.Add(value.ToStringValue()); } } } if (arguments.Names.Contains("classes")) { var classes = arguments["classes"]; if (classes.Type == FluidValues.String) { var values = classes.ToStringValue().Split(' ', StringSplitOptions.RemoveEmptyEntries); foreach (var value in values) { objectValue.Classes.Add(value); } } else if (classes.Type == FluidValues.Array) { foreach (var value in classes.Enumerate()) { objectValue.Classes.Add(value.ToStringValue()); } } } if (arguments.Names.Contains("attributes")) { var attributes = arguments["attributes"]; if (attributes.Type == FluidValues.String) { var values = JsonConvert.DeserializeObject <Dictionary <string, string> >(attributes.ToStringValue()); foreach (var value in values) { objectValue.Attributes.TryAdd(value.Key, value.Value); } } } if (arguments.Names.Contains("item_attributes")) { var itemAttributes = arguments["item_attributes"]; if (itemAttributes.Type == FluidValues.String) { var values = JsonConvert.DeserializeObject <Dictionary <string, string> >(itemAttributes.ToStringValue()); foreach (var value in values) { objectValue.ItemAttributes.TryAdd(value.Key, value.Value); } } } } } return(Completion.Normal); }
static void ValidateRandom <T>(TextFormat format, TextEncoder encoder) { Validate <T>(GetRandom <T>(), format, encoder); }
public static bool TryParseBoolean(ReadOnlySpan <byte> text, out bool value, out int bytesConsumed, TextEncoder encoder = null) { encoder = encoder == null ? TextEncoder.Utf8 : encoder; bytesConsumed = 0; value = default(bool); if (encoder.IsInvariantUtf8) { return(InvariantUtf8.TryParseBoolean(text, out value, out bytesConsumed)); } if (encoder.IsInvariantUtf16) { ReadOnlySpan <char> textChars = text.NonPortableCast <byte, char>(); int charactersConsumed; bool result = InvariantUtf16.TryParseBoolean(textChars, out value, out charactersConsumed); bytesConsumed = charactersConsumed * sizeof(char); return(result); } return(false); }
private async Task CheckAsync(string source, string expected, TemplateContext context, TextEncoder encoder) { _parser.TryParse(source, out var template, out var error); var result = await template.RenderAsync(context, encoder); Assert.Equal(expected, result); }
public static void Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder, TextWriter writer) { var task = template.RenderAsync(writer, encoder, context); if (!task.IsCompletedSuccessfully) { task.GetAwaiter().GetResult(); } }
public void Run(TcpClient client) { try { logger.Log(this, String.Format("Godot has been activated. Client IP address is {0}", LUtils.GetIpAddress(client))); godotCounter.IncreaseRunning(); stream = new SslStream(client.GetStream(), false, CertificateValidation); stream.AuthenticateAsServer(serverCert, true, SslProtocols.Tls12, false); logger.Log(this, "SSL authentication completed. Starting Handshake."); this.user = Handshake.Run(stream, Log, config); InitSync(); bool running = true; while (running) { ConnectionCommand command = TextEncoder.ReadCommand(stream); switch (command) { case ConnectionCommand.TRUST_CONTACT: Log("TRUST_CONTACT command received."); TrustContact(); break; case ConnectionCommand.UNTRUST_CONTACT: Log("UNTRUST_CONTACT command received."); UntrustContact(); break; case ConnectionCommand.PULL: #if (DEBUG) Log("PULL command received."); #endif Push(); break; case ConnectionCommand.PUSH: #if (DEBUG) Log("PUSH command received."); #endif Pull(); break; case ConnectionCommand.CREATE_ONLIVE_TUNNEL: Log("CREATE_ONLIVE_TUNNEL command received."); CreateOnliveTunnel(); break; case ConnectionCommand.END_CONNECTION: Log("END_CONNECTION command received."); running = false; break; default: throw new ChatovatkoException(this, "Received unknown command."); } } } catch (Exception ex) { logger.Log(this, String.Format("Godot has crashed. Exception:\n{0}\n{1}\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace)); } finally { stream.Close(); client.Close(); godotCounter.IncreaseDestroyed(); logger.Log(this, "Godot has died."); } }
void ILiquidFrameworkElementRenderer.Render(ILiquidFrameworkElementRenderer baseRenderer, ILavaRenderContext context, TextWriter result, TextEncoder encoder) { var dotLiquidContext = ((DotLiquidRenderContext)context).DotLiquidContext; base.Render(dotLiquidContext, result); }
public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context) { await writer.WriteAsync("Hello from MyTag"); return(Completion.Normal); }
public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context) {
public static async ValueTask <Completion> WriteToAsync( List <FilterArgument> argumentsList, IReadOnlyList <Statement> statements, TextWriter writer, TextEncoder encoder, TemplateContext context) { var services = ((LiquidTemplateContext)context).Services; var layoutAccessor = services.GetRequiredService <ILayoutAccessor>(); var logger = services.GetRequiredService <ILogger <ZoneTag> >(); string position = null; string name = null; for (var i = 0; i < argumentsList.Count; i++) { var argument = argumentsList[i]; // check common case if (String.IsNullOrEmpty(argument.Name) && argument.Expression is LiteralExpression literalExpression) { name = literalExpression.Value.ToStringValue(); continue; } switch (argument.Name) { case "position": position = (await argument.Expression.EvaluateAsync(context)).ToStringValue(); break; case null: case "name": case "": name ??= (await argument.Expression.EvaluateAsync(context)).ToStringValue(); break; } } if (statements != null && statements.Count > 0) { var content = new ViewBufferTextWriterContent(); var completion = await statements.RenderStatementsAsync(content, encoder, context); if (completion != Completion.Normal) { return(completion); } var layout = await layoutAccessor.GetLayoutAsync(); var zone = layout.Zones[name]; if (zone is Shape shape) { await shape.AddAsync(content, position); } else { logger.LogWarning( "Unable to add shape to the zone using the {{% zone %}} Liquid tag because the zone's type " + "is \"{ActualType}\" instead of the expected {ExpectedType}", zone.GetType().FullName, nameof(Shape)); } } return(Completion.Normal); }
public static async ValueTask <Completion> WriteToAsync(List <FilterArgument> argumentsList, TextWriter writer, TextEncoder encoder, TemplateContext context) { var services = ((LiquidTemplateContext)context).Services; var layout = await services.GetRequiredService <ILayoutAccessor>().GetLayoutAsync(); var displayHelper = services.GetRequiredService <IDisplayHelper>(); var arguments = new NamedExpressionList(argumentsList); var nameExpression = arguments["name", 0] ?? throw new ArgumentException("render_section tag requires a name argument"); var name = (await nameExpression.EvaluateAsync(context)).ToStringValue(); var requiredExpression = arguments["required", 1]; var required = requiredExpression != null && (await requiredExpression.EvaluateAsync(context)).ToBooleanValue(); var zone = layout.Zones[name]; if (zone.IsNullOrEmpty()) { if (required) { throw new InvalidOperationException("Zone not found while invoking 'render_section': " + name); } return(Completion.Normal); } var htmlContent = await displayHelper.ShapeExecuteAsync(zone); htmlContent.WriteTo(writer, (HtmlEncoder)encoder); return(Completion.Normal); }
public static Task RenderAsync(this ILiquidTemplateManager manager, string template, TextWriter writer, TextEncoder encoder, Action <Scope> scopeAction) => manager.RenderAsync(template, writer, encoder, null, scopeAction);
public static Task RenderAsync(this ILiquidTemplateManager manager, string template, TextWriter writer, TextEncoder encoder, object model) => manager.RenderAsync(template, writer, encoder, model, scopeAction: null);
public static Task <string> RenderAsync(this ILiquidTemplateManager manager, string template, TextEncoder encoder) => manager.RenderAsync(template, encoder, null, scopeAction: null);
public abstract void WriteTo(TextWriter writer, TextEncoder encoder, CultureInfo cultureInfo);
public static string Render(this IFluidTemplate template, TemplateContext context, TextEncoder encoder) { var task = template.RenderAsync(context, encoder); return(task.IsCompletedSuccessfully ? task.Result : task.GetAwaiter().GetResult()); }
public override void WriteTo(TextWriter writer, TextEncoder encoder, CultureInfo cultureInfo) { }
public static ValueTask <string> RenderAsync(this IFluidTemplate template, TemplateContext context, TextEncoder encoder) { if (context == null) { ExceptionHelper.ThrowArgumentNullException(nameof(context)); } if (template == null) { return(ExceptionHelper.ThrowArgumentNullException <ValueTask <string> >(nameof(template))); }
public static async ValueTask <Completion> WriteToAsync(Expression expression, TextWriter writer, TextEncoder encoder, TemplateContext context) { var services = ((LiquidTemplateContext)context).Services; var viewContextAccessor = services.GetRequiredService <ViewContextAccessor>(); var viewContext = viewContextAccessor.ViewContext; if (viewContext.View is RazorView razorView && razorView.RazorPage is Razor.IRazorPage razorPage) { razorPage.ViewLayout = (await expression.EvaluateAsync(context)).ToStringValue(); } return(Completion.Normal); }
public override async Task <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context) { if (!context.AmbientValues.TryGetValue("Services", out var servicesObj)) { throw new ArgumentException("Services missing while invoking 'cache' block"); } var services = servicesObj as IServiceProvider; var dynamicCache = services.GetService <IDynamicCacheService>(); var cacheScopeManager = services.GetService <ICacheScopeManager>(); var loggerFactory = services.GetService <ILoggerFactory>(); var logger = loggerFactory.CreateLogger <CacheStatement>(); if (dynamicCache == null || cacheScopeManager == null) { logger.LogInformation(@"Liquid cache block entered without an available IDynamicCacheService or ICacheScopeManager. The contents of the cache block will not be cached. To enable caching, make sure that a feature that contains an implementation of IDynamicCacheService and ICacheScopeManager is enabled (for example, 'Dynamic Cache')."); await writer.WriteAsync(await EvaluateStatementsAsync(encoder, context)); return(Completion.Normal); } // TODO: Create a configuration setting in the UI var debugMode = false; var arguments = (FilterArguments)(await _arguments.EvaluateAsync(context)).ToObjectValue(); var cacheKey = arguments.At(0).ToStringValue(); var contexts = arguments["vary_by"].ToStringValue(); var tags = arguments["dependencies"].ToStringValue(); var durationString = arguments["expires_after"].ToStringValue(); var slidingDurationString = arguments["expires_sliding"].ToStringValue(); var cacheContext = new CacheContext(cacheKey) .AddContext(contexts.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)) .AddTag(tags.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)); if (TimeSpan.TryParse(durationString, out var duration)) { cacheContext.WithExpiryAfter(duration); } if (TimeSpan.TryParse(slidingDurationString, out var slidingDuration)) { cacheContext.WithExpirySliding(slidingDuration); } var cacheResult = await dynamicCache.GetCachedValueAsync(cacheContext); if (cacheResult != null) { await writer.WriteAsync(cacheResult); return(Completion.Normal); } cacheScopeManager.EnterScope(cacheContext); String content; try { content = await EvaluateStatementsAsync(encoder, context); } finally { cacheScopeManager.ExitScope(); } if (debugMode) { var debugContent = new StringWriter(); debugContent.WriteLine($"<!-- CACHE BLOCK: {cacheContext.CacheId} ({Guid.NewGuid()})"); debugContent.WriteLine($" VARY BY: {String.Join(", ", cacheContext.Contexts)}"); debugContent.WriteLine($" DEPENDENCIES: {String.Join(", ", cacheContext.Tags)}"); debugContent.WriteLine($" EXPIRES ON: {cacheContext.ExpiresOn}"); debugContent.WriteLine($" EXPIRES AFTER: {cacheContext.ExpiresAfter}"); debugContent.WriteLine($" EXPIRES SLIDING: {cacheContext.ExpiresSliding}"); debugContent.WriteLine("-->"); debugContent.WriteLine(content); debugContent.WriteLine($"<!-- END CACHE BLOCK: {cacheContext.CacheId} -->"); content = debugContent.ToString(); } await dynamicCache.SetCachedValueAsync(cacheContext, content); await writer.WriteAsync(content); return(Completion.Normal); }
public override ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context, FilterArgument[] arguments, List <Statement> statements) { return(new HelperStatement(new ArgumentsExpression(arguments), null, statements).WriteToAsync(writer, encoder, context)); }
public override void WriteTo(TextWriter writer, TextEncoder encoder, CultureInfo cultureInfo) { AssertWriteToParameters(writer, encoder, cultureInfo); writer.Write(encoder.Encode(ToStringValue())); }
public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context) { if (!context.AmbientValues.TryGetValue("Services", out var servicesValue)) { throw new ArgumentException("Services missing while invoking 'helper'"); } var services = servicesValue as IServiceProvider; var viewContextAccessor = services.GetRequiredService <ViewContextAccessor>(); var viewContext = viewContextAccessor.ViewContext; var arguments = (FilterArguments)(await _arguments.EvaluateAsync(context)).ToObjectValue(); var helper = _helper ?? arguments["helper_name"].Or(arguments.At(0)).ToStringValue(); var factory = services.GetRequiredService <LiquidTagHelperFactory>(); // Each tag is a singleton, as views are if (_activator == null) { lock (this) { if (_activator == null) { _activator = factory.GetActivator(helper, arguments.Names); } } } if (_activator == LiquidTagHelperActivator.None) { return(Completion.Normal); } var tagHelper = factory.CreateTagHelper(_activator, viewContext, arguments, out var contextAttributes, out var outputAttributes); ViewBufferTextWriterContent content = null; if (Statements != null && Statements.Count > 0) { content = new ViewBufferTextWriterContent(); var completion = Completion.Break; for (var index = 0; index < Statements.Count; index++) { completion = await Statements[index].WriteToAsync(content, encoder, context); if (completion != Completion.Normal) { return(completion); } } } var tagHelperContext = new TagHelperContext(contextAttributes, new Dictionary <object, object>(), Guid.NewGuid().ToString("N")); TagHelperOutput tagHelperOutput = null; if (content != null) { tagHelperOutput = new TagHelperOutput( helper, outputAttributes, (_, e) => Task.FromResult(new DefaultTagHelperContent().AppendHtml(content)) ); tagHelperOutput.Content.AppendHtml(content); } else { tagHelperOutput = new TagHelperOutput( helper, outputAttributes, (_, e) => Task.FromResult <TagHelperContent>(new DefaultTagHelperContent()) ); } await tagHelper.ProcessAsync(tagHelperContext, tagHelperOutput); tagHelperOutput.WriteTo(writer, (HtmlEncoder)encoder); return(Completion.Normal); }
static void Validate <T>(long value, TextFormat format, TextEncoder encoder) { Validate <T>(unchecked ((ulong)value), format, encoder); }
public override ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context) { return(Continue); }
public static async ValueTask <Completion> WriteToAsync(ValueTuple <Expression, List <FilterArgument> > arguments, TextWriter writer, TextEncoder encoder, TemplateContext context) { var objectValue = (await arguments.Item1.EvaluateAsync(context)).ToObjectValue(); if (objectValue is IShape shape) { var attributes = arguments.Item2; foreach (var attribute in attributes) { shape.Attributes[attribute.Name.Replace('_', '-')] = (await attribute.Expression.EvaluateAsync(context)).ToStringValue(); } } return(Completion.Normal); }
private void Pull() { #if (DEBUG) Log("Pulling started."); Log("Receiving PushCapsula."); #endif PushCapsula capsula = TextEncoder.ReadJson <PushCapsula>(stream); PushResponse response = new PushResponse() { MessageIds = new List <long>() }; using (Context context = new Context(config)) { #if (DEBUG) Log($"Receiving and saving {capsula.recepientIds.Count} blobs."); #endif foreach (var messageRecepientId in capsula.recepientIds) { BlobMessages blobMessage = new BlobMessages() { Content = BinaryEncoder.ReceiveBytes(stream), RecepientId = (int)messageRecepientId, SenderId = user.UserId }; context.BlobMessages.Add(blobMessage); context.SaveChanges(); if (messageRecepientId == user.UserId) { response.MessageIds.Add(blobMessage.Id); messagesIdsUploaded.Add(blobMessage.Id); } context.SaveChanges(); } #if (DEBUG) Log($"Deleting {capsula.messageToDeleteIds.Count} blobs."); #endif foreach (var toDeleteId in capsula.messageToDeleteIds) { var toDelete = context.BlobMessages .Where(u => u.RecepientId == user.UserId && u.Id == toDeleteId).SingleOrDefault(); if (toDelete != null) { context.BlobMessages.Remove(toDelete); } } context.SaveChanges(); } #if (DEBUG) Log("Sending push response."); #endif TextEncoder.SendJson(stream, response); #if (DEBUG) Log("Pulling ended."); #endif }
public void TestLowerBound() { TextEncoder encoder = new TextEncoder(); encoder.Convert(-1f); }
private void Push() { #if (DEBUG) Log("Pushing started."); #endif using (Context context = new Context(config)) { PullCapsula capsula = new PullCapsula(); List <PullUser> pullUsers = new List <PullUser>(); foreach (Users user in context.Users.Where(u => !userIdsUploaded.Contains(u.Id))) { PullUser pullUser = new PullUser() { PublicCertificate = user.PublicCertificate, UserId = user.Id, UserName = user.UserName }; pullUsers.Add(pullUser); userIdsUploaded.Add(user.Id); } capsula.Users = pullUsers; #if (DEBUG) Log($"{pullUsers.Count} users will be pushed."); #endif capsula.TrustedUserIds = new List <long>(); foreach (var userId in ( from userKeys in context.UsersKeys where userKeys.Trusted == true && userKeys.SenderId == user.UserId select new { userKeys.RecepientId })) { capsula.TrustedUserIds.Add(userId.RecepientId); } #if (DEBUG) Log($"{capsula.TrustedUserIds.Count} users is trusted by host."); #endif List <byte[]> messagesBlobsToSend = new List <byte[]>(); List <byte[]> aesBlobsToSend = new List <byte[]>(); List <PullMessage> pullMessages = new List <PullMessage>(); foreach (var message in from messages in context.BlobMessages orderby messages.Id ascending //Message order must be respected where messages.RecepientId == user.UserId //Messages of connected user where !messagesIdsUploaded.Contains(messages.Id) //New messages join keys in context.UsersKeys on messages.RecepientId equals keys.SenderId //Keys sended by connected user where keys.Trusted == true //Only trusted where messages.SenderId == keys.RecepientId //Trusted information just only about sending user select new { messages.SenderId, messages.Content, messages.Id } ) { pullMessages.Add(new PullMessage() { PublicId = message.Id, SenderId = message.SenderId }); messagesBlobsToSend.Add(message.Content); messagesIdsUploaded.Add(message.Id); } capsula.Messages = pullMessages; #if (DEBUG) Log($"{messagesBlobsToSend.Count} messageBlobs will be pushed."); #endif capsula.AesKeysUserIds = new List <long>(); foreach (var user in from userKeys in context.UsersKeys where userKeys.RecepientId == user.UserId where !aesKesUserIdsUploaded.Contains(userKeys.SenderId) select new { userKeys.SenderId, userKeys.EncryptedAesKey }) { capsula.AesKeysUserIds.Add(user.SenderId); aesKesUserIdsUploaded.Add(user.SenderId); aesBlobsToSend.Add(user.EncryptedAesKey); } #if (DEBUG) Log($"{capsula.AesKeysUserIds.Count} AES keys will be pushed."); Log($"Sending PullCapsula."); #endif TextEncoder.SendJson(stream, capsula); #if (DEBUG) Log($"Sending AES keys."); #endif foreach (byte[] data in aesBlobsToSend) { BinaryEncoder.SendBytes(stream, data); } #if (DEBUG) Log($"Sending Messages content."); #endif foreach (byte[] data in messagesBlobsToSend) { BinaryEncoder.SendBytes(stream, data); } } #if (DEBUG) Log("Pushing completed."); #endif }
public void TestUpperBound() { TextEncoder encoder = new TextEncoder(); encoder.Convert(100.001f); }
public static async ValueTask <Completion> WriteToAsync(ValueTuple <Expression, List <FilterArgument> > arguments, TextWriter writer, TextEncoder encoder, TemplateContext context) { var objectValue = (await arguments.Item1.EvaluateAsync(context)).ToObjectValue() as dynamic; if (objectValue is Shape shape) { if (shape.Metadata.Type == "PagerSlim") { foreach (var argument in arguments.Item2) { var propertyName = argument.Name.ToPascalCaseUnderscore(); if (_properties.Contains(propertyName)) { objectValue[propertyName] = (await argument.Expression.EvaluateAsync(context)).ToStringValue(); } } } var expressions = new NamedExpressionList(arguments.Item2); if (shape.Metadata.Type == "PagerSlim" || shape.Metadata.Type == "Pager") { if (expressions.HasNamed("item_classes")) { var itemClasses = await expressions["item_classes"].EvaluateAsync(context); if (itemClasses.Type == FluidValues.String) { var values = itemClasses.ToStringValue().Split(' ', StringSplitOptions.RemoveEmptyEntries); foreach (var value in values) { objectValue.ItemClasses.Add(value); } } else if (itemClasses.Type == FluidValues.Array) { foreach (var value in itemClasses.Enumerate()) { objectValue.ItemClasses.Add(value.ToStringValue()); } } } if (expressions.HasNamed("classes")) { var classes = await expressions["classes"].EvaluateAsync(context); if (classes.Type == FluidValues.String) { var values = classes.ToStringValue().Split(' ', StringSplitOptions.RemoveEmptyEntries); foreach (var value in values) { objectValue.Classes.Add(value); } } else if (classes.Type == FluidValues.Array) { foreach (var value in classes.Enumerate()) { objectValue.Classes.Add(value.ToStringValue()); } } } if (expressions.HasNamed("attributes")) { var attributes = await expressions["attributes"].EvaluateAsync(context); if (attributes.Type == FluidValues.String) { var values = JsonConvert.DeserializeObject <Dictionary <string, string> >(attributes.ToStringValue()); foreach (var value in values) { objectValue.Attributes.TryAdd(value.Key, value.Value); } } } if (expressions.HasNamed("item_attributes")) { var itemAttributes = await expressions["item_attributes"].EvaluateAsync(context); if (itemAttributes.Type == FluidValues.String) { var values = JsonConvert.DeserializeObject <Dictionary <string, string> >(itemAttributes.ToStringValue()); foreach (var value in values) { objectValue.ItemAttributes.TryAdd(value.Key, value.Value); } } } } } return(Completion.Normal); }