using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace zero.TagHelpers; [HtmlTargetElement("app-icon", TagStructure = TagStructure.NormalOrSelfClosing)] public class IconTagHelper : TagHelper { public string Symbol { get; set; } public int Size { get; set; } = -1; public decimal Stroke { get; set; } = -1; public string Class { get; set; } public string Set { get; set; } [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } = null!; private IconOptions _options; private readonly IFileVersionProvider _fileVersionProvider; private readonly ILogger _logger; public IconTagHelper(IOptionsMonitor options, ILogger logger, IFileVersionProvider fileVersionProvider) { _options = options.CurrentValue; _logger = logger; _fileVersionProvider = fileVersionProvider; options.OnChange(val => _options = val); } public override void Process(TagHelperContext context, TagHelperOutput output) { IconSetOptions set = Set.HasValue() ? _options.Sets.FirstOrDefault(x => x.Key == Set) : _options; if (set == null || set.Path.IsNullOrWhiteSpace()) { _logger.LogWarning("Could not render . Could not find icon set {set}.", Set); output.SuppressOutput(); return; } int size = Size < 0 ? (set.DefaultSize ?? _options.DefaultSize ?? 18) : Size; decimal stroke = Stroke < 0 ? (set.DefaultStrokeWidth ?? _options.DefaultStrokeWidth ?? 2) : Stroke; string strokeStr = stroke.ToString().Replace(',', '.'); string[] classes = new[] { set.CssClass.HasValue() ? set.CssClass : _options.CssClass, Class }.Where(x => x.HasValue()).Distinct().ToArray(); output.TagName = "svg"; output.Attributes.SetAttribute("class", string.Join(" ", classes)); output.Attributes.SetAttribute("width", size); output.Attributes.SetAttribute("height", size); output.Attributes.SetAttribute("xmlns", "http://www.w3.org/2000/svg"); output.Attributes.SetAttribute("stroke-width", strokeStr); output.Attributes.SetAttribute("data-symbol", Symbol); output.Content.SetHtmlContent(BuildIcon(Symbol, size, strokeStr, setKey: Set)); } public string BuildIcon(string symbol, int size = 18, string stroke = "2", string classes = null, bool withSvg = false, string setKey = null) { IconSetOptions set = setKey.HasValue() ? _options.Sets.FirstOrDefault(x => x.Key == setKey) : _options; if (set == null || set.Path.IsNullOrWhiteSpace()) { _logger.LogWarning("Could not render (build icon). Could not find icon set {set}.", Set); return null; } string path = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, set.Path); string inner = $""; if (!withSvg) { return inner; } return $"{inner}"; } }