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 = LiquidViewFilters.LowerKebabToPascalCase(name); 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(new[] { ' ' }, 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()); } } } } } return(Completion.Normal); }
public override async Task <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; if (!context.AmbientValues.TryGetValue("ViewContext", out var viewContext)) { throw new ArgumentException("ViewContext missing while invoking 'helper'"); } var arguments = (FilterArguments)(await _arguments.EvaluateAsync(context)).ToObjectValue(); var helper = _helper ?? arguments.At(0).ToStringValue(); var tagHelperSharedState = services.GetRequiredService <TagHelperSharedState>(); if (tagHelperSharedState.TagHelperDescriptors == null) { lock (tagHelperSharedState) { if (tagHelperSharedState.TagHelperDescriptors == null) { var razorEngine = services.GetRequiredService <RazorEngine>(); var tagHelperFeature = razorEngine.Features.OfType <ITagHelperFeature>().FirstOrDefault(); tagHelperSharedState.TagHelperDescriptors = tagHelperFeature.GetDescriptors().ToList(); } } } if (_descriptor == null) { lock (this) { var descriptors = tagHelperSharedState.TagHelperDescriptors .Where(d => d.TagMatchingRules.Any(rule => ((rule.TagName == "*") || rule.TagName == helper) && rule.Attributes.All(attr => arguments.Names.Any(name => { if (String.Equals(name, attr.Name, StringComparison.OrdinalIgnoreCase)) { return(true); } name = name.Replace("_", "-"); if (attr.Name.StartsWith(AspPrefix) && String.Equals(name, attr.Name.Substring(AspPrefix.Length), StringComparison.OrdinalIgnoreCase)) { return(true); } if (String.Equals(name, attr.Name, StringComparison.OrdinalIgnoreCase)) { return(true); } return(false); })))); _descriptor = descriptors.FirstOrDefault(); if (_descriptor == null) { return(Completion.Normal); } } } var tagHelperType = Type.GetType(_descriptor.Name + ", " + _descriptor.AssemblyName); var _tagHelperActivator = _tagHelperActivators.GetOrAdd(tagHelperType, key => { var genericFactory = typeof(ReusableTagHelperFactory <>).MakeGenericType(key); var factoryMethod = genericFactory.GetMethod("CreateTagHelper"); return(Delegate.CreateDelegate(typeof(Func <ITagHelperFactory, ViewContext, ITagHelper>), factoryMethod) as Func <ITagHelperFactory, ViewContext, ITagHelper>); }); var tagHelperFactory = services.GetRequiredService <ITagHelperFactory>(); var tagHelper = _tagHelperActivator(tagHelperFactory, (ViewContext)viewContext); var attributes = new TagHelperAttributeList(); foreach (var name in arguments.Names) { var propertyName = LiquidViewFilters.LowerKebabToPascalCase(name); var found = false; foreach (var attribute in _descriptor.BoundAttributes) { if (propertyName == attribute.GetPropertyName()) { found = true; var setter = _tagHelperSetters.GetOrAdd(attribute.DisplayName, key => { var propertyInfo = tagHelperType.GetProperty(propertyName); var propertySetter = propertyInfo.GetSetMethod(); var invokeType = typeof(Action <,>).MakeGenericType(tagHelperType, propertyInfo.PropertyType); var setterDelegate = Delegate.CreateDelegate(invokeType, propertySetter); Action <ITagHelper, FluidValue> result = (h, v) => { object value = null; if (attribute.IsEnum) { value = Enum.Parse(propertyInfo.PropertyType, v.ToStringValue()); } else if (attribute.IsStringProperty) { value = v.ToStringValue(); } else if (propertyInfo.PropertyType == typeof(Boolean)) { value = Convert.ToBoolean(v.ToStringValue()); } else { value = v.ToObjectValue(); } setterDelegate.DynamicInvoke(new[] { h, value }); }; return(result); }); try { setter(tagHelper, arguments[name]); } catch (ArgumentException e) { throw new ArgumentException("Incorrect value type assigned to a tag.", name, e); } break; } } if (!found) { attributes.Add(new TagHelperAttribute(name.Replace("_", "-"), arguments[name].ToObjectValue())); } } var content = new StringWriter(); if (Statements?.Any() ?? false) { Completion 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(attributes, new Dictionary <object, object>(), Guid.NewGuid().ToString("N")); var tagHelperOutput = new TagHelperOutput(helper, attributes, (_, e) => Task.FromResult(new DefaultTagHelperContent().AppendHtml(content.ToString()))); tagHelperOutput.Content.AppendHtml(content.ToString()); await tagHelper.ProcessAsync(tagHelperContext, tagHelperOutput); tagHelperOutput.WriteTo(writer, HtmlEncoder.Default); return(Completion.Normal); }