Files
AcdiuTools/TagHelpers/BsIconTagHelper.cs
2026-04-25 17:04:42 +08:00

95 lines
4.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;
namespace AcdiuTools.TagHelpers
{
/// <summary>
/// <see langword="Bootstrap Icons"></see> SVG Sprite 封装标签
/// 用法: <bsicon i="heart-fill" w="16" h="16" f="red" />
/// </summary>
[HtmlTargetElement("bsicon")]
public class BsIconTagHelper : TagHelper
{
// 路径指向你存放总 SVG 的位置
/// <summary>
/// 表示用于引用图标符号的 <see langword="Bootstrap Icons"></see> SVG矢量图库文件的相对路径
/// </summary>
/// <remarks>此路径应指向包含所有 <see langword="Bootstrap"></see> 图标定义的SVG文件<br/>
/// 如果图标库被移动或升级,则需要更新该值</remarks>
const string spritePath = "/lib/bootstrap-icons-1.13.1/bootstrap-icons.svg";
/// <summary>
/// 图标名称 (必填)
/// </summary>
[HtmlAttributeName("i")]
public required string IconName { get; set; }
/// <summary>
/// 宽度 (默认为空,若为空时设置了高度,则使用高度的值,否则使用默认值 14)
/// </summary>
[HtmlAttributeName("w")]
public string Width { get; set; } = string.Empty;
/// <summary>
/// 高度 (默认为空,若为空时设置了宽度,则使用宽度的值,否则使用默认值 14)
/// </summary>
[HtmlAttributeName("h")]
public string Height { get; set; } = string.Empty;
/// <summary>
/// 填充颜色 (默认 currentColor 即当前元素颜色)
/// </summary>
[HtmlAttributeName("f")]
public string Fill { get; set; } = "currentColor";
/// <summary>
/// 自定义 class 名称,允许用户添加额外的样式类 (默认空)
/// </summary>
[HtmlAttributeName("cn")]
public string ClassName { get; set; } = string.Empty;
/// <summary>
/// 根据指定的图标名称和属性处理标签助手以渲染SVG矢量图标
/// </summary>
/// <remarks>若未指定图标名称或为空则输出被抑制且不生成SVG<br/>
/// 渲染后,该方法会将原始标签替换为&lt;svg&gt;元素并设置标准的SVG属性<br/>
/// 包括类名、宽度、高度、填充颜色和图标ID名称。该SVG引用了 <see langword="Bootstrap Icons"></see> 中的图标<br/>
/// 使用&lt;use&gt;元素引用的矢量图形</remarks>
/// <param name="context">用于标签辅助程序执行的上下文包含当前HTML标签及其属性的相关信息</param>
/// <param name="output">标签辅助器的输出用于修改渲染的HTML元素及其内容</param>
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (string.IsNullOrWhiteSpace(IconName))
{
output.SuppressOutput(); // 如果没写图标名,则不渲染
return;
}
// 1. 将外层标签替换为 <svg>
output.TagName = "svg";
output.TagMode = TagMode.StartTagAndEndTag;
// 2. 设置 SVG 基础属性
// 合并默认 class "bi" 和用户自定义的 cn
var finalClass = string.IsNullOrWhiteSpace(ClassName) ? "" : $"{ClassName}";
output.Attributes.SetAttribute("class", finalClass);
// 如果设置了 w 或 h则优先使用它们否则使用 wh 的值
// 设定机制:
// 如果 w 和 h 中任意一个不为空,则使用不为空的 w 或 h 的值同时设置宽高;
// 如果 w 和 h 都不为空,则分别使用它们设置宽高;
// 如果 w 和 h 都为空,则使用默认的 14 同时设置宽高
output.Attributes.SetAttribute("width", !string.IsNullOrWhiteSpace(Width) ? Width : (!string.IsNullOrWhiteSpace(Height) ? Height : "14"));
output.Attributes.SetAttribute("height", !string.IsNullOrWhiteSpace(Height) ? Height : (!string.IsNullOrWhiteSpace(Width) ? Width : "14"));
output.Attributes.SetAttribute("fill", Fill);
output.Attributes.SetAttribute("viewBox", "0 0 16 16"); // 保证矢量对齐
//output.Attributes.SetAttribute("xmlns", "http://www.w3.org/2000/svg");
// 3. 构造内部的 <use> 节点
var content = $@"<use xlink:href=""{spritePath}#{IconName}""></use>";
output.Content.SetHtmlContent(content);
}
}
}