Skip to content

Conversation

@AiYuZhen
Copy link
Collaborator

@AiYuZhen AiYuZhen commented Nov 10, 2025

#7091

Link issues

fixes #{issue number}

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Enable Link components to inject tags into the page head through a new IsAddToHead parameter and a custom JS interop module, while preserving existing rendering behavior when the feature is not enabled.

New Features:

  • Add IsAddToHead parameter to Link component to support injecting link tags into the document head
  • Introduce a JS interop module to insert and deduplicate head link elements

Enhancements:

  • Migrate Link component to BootstrapModuleComponentBase and apply BootstrapModuleAutoLoader for manual JS invocation

Tests:

  • Add unit test verifying that Link suppresses direct markup when IsAddToHead is true

@bb-auto
Copy link

bb-auto bot commented Nov 10, 2025

Thanks for your PR, @AiYuZhen. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Nov 10, 2025

Reviewer's Guide

Adds an IsAddToHead flag to the Link component enabling optional insertion of tags into the document head via a JS module, avoids duplicate tags, and updates unit tests.

Sequence diagram for Link component rendering with IsAddToHead=true

sequenceDiagram
    participant LinkComponent
    participant Browser
    participant JSModule
    LinkComponent->>Browser: Render (firstRender)
    LinkComponent->>JSModule: Invoke init({Href, Rel})
    JSModule->>Browser: Check for existing <link> in head
    alt Link not found
        JSModule->>Browser: Append new <link> to head
    else Link found
        JSModule->>Browser: Do nothing
    end
Loading

Class diagram for updated Link component

classDiagram
    class Link {
        +string? Version
        +bool IsAddToHead
        +IVersionService VersionService
        +string GetHref()
        +Task OnAfterRenderAsync(bool firstRender)
    }
Loading

File-Level Changes

Change Details Files
Introduce head-injection support in the Link component
  • Add IsAddToHead parameter with default false
  • Switch base class to BootstrapModuleComponentBase and disable auto-loader
  • Wrap markup in a conditional to skip inline rendering when head injection is used
  • Implement OnAfterRenderAsync to invoke JS init on first render if head injection is enabled
src/BootstrapBlazor/Components/HtmlTag/Link.razor
src/BootstrapBlazor/Components/HtmlTag/Link.razor.cs
Add JS module for link injection into head
  • Create init function to detect existing link tags by href and rel
  • Append new link element to document.head when no duplicate is found
src/BootstrapBlazor/Components/HtmlTag/Link.razor.js
Expand unit tests for the new head-injection behavior
  • Add Link_IsAddToHead_True test to assert no inline markup is rendered when head injection is enabled
test/UnitTest/Components/LinkTest.cs

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bb-auto bb-auto bot requested a review from ArgoZhang November 10, 2025 23:09
sourcery-ai[bot]
sourcery-ai bot previously approved these changes Nov 10, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Consider renaming IsAddToHead to a name like AddToHead or AppendToHead to better follow .NET boolean property naming conventions.
  • Add disposal or parameter‐change logic to remove or update injected link tags when the component is unmounted or its parameters change to prevent stale entries.
  • In the JavaScript init function, use the URL API (e.g. new URL(href, document.baseURI)) instead of string concatenation for more robust href comparisons and to support relative URLs.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider renaming IsAddToHead to a name like AddToHead or AppendToHead to better follow .NET boolean property naming conventions.
- Add disposal or parameter‐change logic to remove or update injected link tags when the component is unmounted or its parameters change to prevent stale entries.
- In the JavaScript init function, use the URL API (e.g. new URL(href, document.baseURI)) instead of string concatenation for more robust href comparisons and to support relative URLs.

## Individual Comments

### Comment 1
<location> `src/BootstrapBlazor/Components/HtmlTag/Link.razor.js:2-3` </location>
<code_context>
+export function init(options) {
+    const href = options.href;
+    const rel = options.rel;
+    const links = document.head.getElementsByTagName("link");
+    // 遍历所有link元素
</code_context>

<issue_to_address>
**issue:** Consider normalizing option property casing for consistency.

The C# object uses 'Href' and 'Rel', while the JS expects 'href' and 'rel'. Please align property names to prevent undefined values.
</issue_to_address>

### Comment 2
<location> `src/BootstrapBlazor/Components/HtmlTag/Link.razor.js:8` </location>
<code_context>
+    // 遍历所有link元素
+    for (let i = 0; i < links.length; i++) {
+        const hlink = links[i];
+        var nhref = hlink.baseURI + href;
+        if (hlink.href == nhref && hlink.rel == rel) {
+            return;
</code_context>

<issue_to_address>
**issue (bug_risk):** The construction of nhref may not match the actual href attribute value.

Directly concatenating baseURI and href can lead to incorrect URLs if href is absolute or already includes the base URI. Use proper URL resolution or compare hlink.href and href directly.
</issue_to_address>

### Comment 3
<location> `src/BootstrapBlazor/Components/HtmlTag/Link.razor.js:2` </location>
<code_context>
    const href = options.href;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/use-object-destructuring))

```suggestion
    const {href} = options;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

### Comment 4
<location> `src/BootstrapBlazor/Components/HtmlTag/Link.razor.js:3` </location>
<code_context>
    const rel = options.rel;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/use-object-destructuring))

```suggestion
    const {rel} = options;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

### Comment 5
<location> `src/BootstrapBlazor/Components/HtmlTag/Link.razor.js:8` </location>
<code_context>

</code_context>

<issue_to_address>
**issue (code-quality):** Use `const` or `let` instead of `var`. ([`avoid-using-var`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/avoid-using-var))

<details><summary>Explanation</summary>`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code).
`let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than
function-scoped.

From the [Airbnb JavaScript Style Guide](https://airbnb.io/javascript/#references--prefer-const)
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@AiYuZhen AiYuZhen changed the title 添加 IsAddToHead 参数,支持将 link 标签添加到 head 元素中。 feat(Link):添加 IsAddToHead 参数 Nov 10, 2025
@codecov
Copy link

codecov bot commented Nov 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (e7d93b0) to head (d6272ac).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #7092   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          745       746    +1     
  Lines        32556     32568   +12     
  Branches      4512      4514    +2     
=========================================
+ Hits         32556     32568   +12     
Flag Coverage Δ
BB 100.00% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

优化代码。
@AiYuZhen AiYuZhen changed the title feat(Link):添加 IsAddToHead 参数 feat(Link):添加 AddToHead 参数 Nov 10, 2025
@AiYuZhen AiYuZhen closed this Nov 11, 2025
@AiYuZhen
Copy link
Collaborator Author

AiYuZhen commented Nov 11, 2025

通过 BootstrapBlazor 提供的 js 框架 utility.js 里的 addLink 方法可以实现。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant