Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/BootstrapBlazor.Server/Components/Pages/Error.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@page "/error"

@page "/error"

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
Expand All @@ -13,4 +12,4 @@
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
</p>
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private Task OnMaxSelectedCountExceed()

private Task OnTreeItemChecked(List<TreeViewItem<TreeFoo>> items)
{
Logger2.Log($"当前共选中{items.Count}项");
Logger2.Log($"当前共选中 {items.Count} 项");
return Task.CompletedTask;
}

Expand All @@ -201,9 +201,7 @@ private static List<TreeFoo> GetDraggableItems()

new() { Text = "Item C", Id = "3", Icon = "fa-solid fa-font-awesome" },
new() { Text = "Item H", Id = "7", ParentId = "3", Icon = "fa-solid fa-font-awesome" },
new() { Text = "Item I", Id = "8", ParentId = "3", Icon = "fa-solid fa-font-awesome" },


new() { Text = "Item I", Id = "8", ParentId = "3", Icon = "fa-solid fa-font-awesome" }
];
return _dragItems;
}
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Tab/TabItemContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TabItemContent : IComponent, IHandlerException, IDisposable
{
/// <summary>
/// <para lang="zh">获得/设置 标签项,默认为 null</para>
/// <para lang="en">Gets or sets the component content. Default is null.</para>
/// <para lang="en">Gets or sets the component content. Default is null</para>
/// </summary>
[Parameter, NotNull]
public TabItem? Item { get; set; }
Expand Down
29 changes: 2 additions & 27 deletions src/BootstrapBlazor/Extensions/LocalizationOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,16 @@ namespace BootstrapBlazor.Components;
internal static class LocalizationOptionsExtensions
{
/// <summary>
/// <para lang="zh">通过系统 JsonLocalizationOptions 获取当前 Json 格式资源配置集合</para>
/// <para lang="en">Get the current Json format resource configuration collection through the system JsonLocalizationOptions</para>
/// <para lang="zh">通过系统 <see cref="JsonLocalizationOptions"/> 获取当前 Json 格式资源配置集合</para>
/// <para lang="en">Get the current Json format resource configuration collection through the system <see cref="JsonLocalizationOptions"/></para>
/// </summary>
/// <param name="option"></param>
/// <param name="assembly"></param>
/// <param name="cultureName"></param>
public static IEnumerable<IConfigurationSection> GetJsonStringFromAssembly(this JsonLocalizationOptions option, Assembly assembly, string cultureName)
{
// <para lang="zh">创建配置 ConfigurationBuilder</para>
// <para lang="en">Create configuration ConfigurationBuilder</para>
var builder = new ConfigurationBuilder();

// <para lang="zh">获取程序集中的资源文件</para>
// <para lang="en">Get the resource file in the assembly</para>
var assemblies = new List<Assembly>() { assembly };

// <para lang="zh">获得主程序集资源文件</para>
// <para lang="en">Get the main assembly resource file</para>
// <para lang="zh">支持合并操作</para>
// <para lang="en">Support merge operation</para>
var entryAssembly = GetEntryAssembly();
if (assembly != entryAssembly)
{
Expand All @@ -49,15 +39,11 @@ public static IEnumerable<IConfigurationSection> GetJsonStringFromAssembly(this

var streams = assemblies.SelectMany(i => option.GetResourceStream(i, cultureName)).ToList();

// <para lang="zh">添加 Json 文件流到配置</para>
// <para lang="en">Add Json file stream to configuration</para>
foreach (var s in streams)
Comment on lines 40 to 42
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Consider protecting stream disposal with a try/finally (or using) to avoid leaks if builder.Build() throws.

If builder.Build() throws, the foreach that disposes streams is never reached and the manifest resource streams are leaked. Ensure stream creation, Build(), and disposal are wrapped so the streams are always disposed even when configuration building fails.

Suggested implementation:

        var assemblies = new List<Assembly>() { assembly };
        var entryAssembly = GetEntryAssembly();
        if (assembly != entryAssembly)
        {
            var streams = assemblies.SelectMany(i => option.GetResourceStream(i, cultureName)).ToList();

            try
            {
                foreach (var s in streams)
                {
                    builder.AddJsonStream(s);
                }
            }
            finally
            {
                foreach (var s in streams)
                {
                    s.Dispose();
                }
            }

To fully satisfy the review comment about protecting against leaks when builder.Build() throws, you should ensure that the call to builder.Build() (wherever it occurs in this method) executes inside the same try block that owns streams, so that the finally above still runs and disposes the streams if Build() fails. For example:

  1. Move builder.Build() into the try block that currently wraps AddJsonStream.
  2. Or, if builder.Build() is outside this if (assembly != entryAssembly) block, lift the try/finally to a scope that encloses both the JSON stream registration and the Build() call, and keep the streams disposal in the corresponding finally.

{
builder.AddJsonStream(s);
}

// <para lang="zh">获得配置外置资源文件</para>
// <para lang="en">Get configuration external resource file</para>
if (option.AdditionalJsonFiles != null)
{
var files = option.AdditionalJsonFiles.Where(f =>
Expand All @@ -71,11 +57,8 @@ public static IEnumerable<IConfigurationSection> GetJsonStringFromAssembly(this
}
}

// <para lang="zh">生成 IConfigurationRoot</para>
// <para lang="en">Generate IConfigurationRoot</para>
var config = builder.Build();

// dispose json stream
foreach (var s in streams)
{
s.Dispose();
Expand All @@ -92,23 +75,17 @@ private static List<Stream> GetResourceStream(this JsonLocalizationOptions optio
var resourceNames = assembly.GetManifestResourceNames();
var ret = new List<Stream>();

// <para lang="zh">如果开启回落机制优先增加回落语言</para>
// <para lang="en">If the fallback mechanism is enabled, priority is given to increasing the fallback language</para>
if (option.EnableFallbackCulture)
{
AddStream(option.FallbackCulture);
}

// <para lang="zh">查找父资源</para>
// <para lang="en">Find parent resources</para>
var parentName = GetParentCultureName(cultureName).Value;
if (!string.IsNullOrEmpty(parentName) && !EqualFallbackCulture(parentName))
{
AddStream(parentName);
}

// <para lang="zh">当前文化资源</para>
// <para lang="en">Current culture resources</para>
if (!EqualFallbackCulture(cultureName))
{
AddStream(cultureName);
Expand All @@ -129,8 +106,6 @@ void AddStream(string name)
}
}

// <para lang="zh">开启回落机制并且当前文化信息与回落语言相同</para>
// <para lang="en">Open the fallback mechanism and the current cultural information is the same as the fallback language</para>
bool EqualFallbackCulture(string name) => option.EnableFallbackCulture && option.FallbackCulture == name;
}

Expand Down
76 changes: 37 additions & 39 deletions src/BootstrapBlazor/Extensions/ToastServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,29 @@ namespace BootstrapBlazor.Components;

/// <summary>
/// <para lang="zh">ToastService 扩展方法</para>
/// <para lang="en">ToastService 扩展方法</para>
/// <para lang="en">ToastService extension methods</para>
/// </summary>
public static class ToastServiceExtensions
{
// 特别备注:此处方法使用三个参数被 UniLite 插件系统使用,请勿删除

/// <summary>
/// <para lang="zh">Toast 调用成功快捷方法</para>
/// <para lang="en">Toast 调用成功快捷方法</para>
/// <para lang="en">Toast success shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
Comment on lines 18 to +21
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Success(this ToastService service, string? title = null, string? content = null, bool autoHide = true) => Success(service, title, content, autoHide, true);

/// <summary>
/// <para lang="zh">Toast 调用成功快捷方法</para>
/// <para lang="en">Toast 调用成功快捷方法</para>
/// <para lang="en">Toast success shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="showClose"><para lang="zh">是否显示关闭按钮 默认 true</para><para lang="en">whetherdisplay关闭button default is true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
/// <param name="showClose"></param>
Comment on lines 28 to +32
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Success(this ToastService service, string? title, string? content, bool autoHide, bool showClose) => service.Show(new ToastOption()
{
Category = ToastCategory.Success,
Expand All @@ -43,23 +41,23 @@ public static Task Success(this ToastService service, string? title, string? con

/// <summary>
/// <para lang="zh">Toast 调用错误快捷方法</para>
/// <para lang="en">Toast 调用错误快捷方法</para>
/// <para lang="en">Toast error shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
Comment on lines 46 to +49
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Error(this ToastService service, string? title = null, string? content = null, bool autoHide = true) => Error(service, title, content, autoHide, true);

/// <summary>
/// <para lang="zh">Toast 调用错误快捷方法</para>
/// <para lang="en">Toast 调用错误快捷方法</para>
/// <para lang="en">Toast error shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="showClose"><para lang="zh">是否显示关闭按钮 默认 true</para><para lang="en">whetherdisplay关闭button default is true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
/// <param name="showClose"></param>
Comment on lines 56 to +60
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Error(this ToastService service, string? title, string? content, bool autoHide, bool showClose) => service.Show(new ToastOption()
{
Category = ToastCategory.Error,
Expand All @@ -71,23 +69,23 @@ public static Task Error(this ToastService service, string? title, string? conte

/// <summary>
/// <para lang="zh">Toast 调用提示信息快捷方法</para>
/// <para lang="en">Toast 调用提示信息快捷方法</para>
/// <para lang="en">Toast information shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
Comment on lines 74 to +77
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Information(this ToastService service, string? title = null, string? content = null, bool autoHide = true) => Information(service, title, content, autoHide, true);

/// <summary>
/// <para lang="zh">Toast 调用提示信息快捷方法</para>
/// <para lang="en">Toast 调用提示信息快捷方法</para>
/// <para lang="en">Toast information shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="showClose"><para lang="zh">是否显示关闭按钮 默认 true</para><para lang="en">whetherdisplay关闭button default is true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
/// <param name="showClose"></param>
Comment on lines 84 to +88
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Information(this ToastService service, string? title, string? content, bool autoHide, bool showClose) => service.Show(new ToastOption()
{
Category = ToastCategory.Information,
Expand All @@ -99,23 +97,23 @@ public static Task Information(this ToastService service, string? title, string?

/// <summary>
/// <para lang="zh">Toast 调用警告信息快捷方法</para>
/// <para lang="en">Toast 调用警告信息快捷方法</para>
/// <para lang="en">Toast warning shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
Comment on lines 102 to +105
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Warning(this ToastService service, string? title = null, string? content = null, bool autoHide = true) => Warning(service, title, content, autoHide, true);

/// <summary>
/// <para lang="zh">Toast 调用警告信息快捷方法</para>
/// <para lang="en">Toast 调用警告信息快捷方法</para>
/// <para lang="en">Toast warning shortcut method</para>
/// </summary>
/// <param name="service"></param>
/// <param name="title"><para lang="zh">Title 属性</para><para lang="en">Title property</para></param>
/// <param name="content"><para lang="zh">Content 属性</para><para lang="en">Content property</para></param>
/// <param name="autoHide"><para lang="zh">自动隐藏属性默认为 true</para><para lang="en">自动隐藏propertydefault is为 true</para></param>
/// <param name="showClose"><para lang="zh">是否显示关闭按钮 默认 true</para><para lang="en">whetherdisplay关闭button default is true</para></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <param name="autoHide"></param>
/// <param name="showClose"></param>
Comment on lines 112 to +116
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter documentation has been completely removed, leaving only empty param tags. While simplifying documentation can be beneficial, completely removing parameter descriptions may reduce code clarity. Consider either keeping brief descriptions or following a consistent documentation standard across the codebase. Empty param tags provide no value and should either contain descriptions or be removed entirely if the project doesn't require parameter documentation.

Copilot uses AI. Check for mistakes.
public static Task Warning(this ToastService service, string? title, string? content, bool autoHide, bool showClose) => service.Show(new ToastOption()
{
Category = ToastCategory.Warning,
Expand Down
Loading