-
-
Notifications
You must be signed in to change notification settings - Fork 994
fix(XMarkdown): handle void elements and isolate component stream status #1590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 Walkthrough概览引入了基于位置的手动HTML解析器替代正则表达式方法,重构了未闭合标签检测机制。新增per-tag计数器和状态追踪,支持区分同一标签的多个实例,并扩展渲染流程以通过标签索引传播流状态信息。 变更内容
代码审查工作量评估🎯 4 (复杂) | ⏱️ ~60 分钟 诗歌
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @Last-Order, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses two critical bugs within the XMarkdown renderer. It significantly improves the HTML parsing logic to accurately recognize and process void elements and self-closing tags, thereby preventing custom components associated with these elements from entering a perpetual loading state. Furthermore, it refactors the Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request effectively addresses two important bugs: the incorrect handling of void elements causing a perpetual loading state, and the shared stream status among multiple component instances. The new implementation of detectUnclosedTags is a significant improvement, providing a more robust parsing mechanism that correctly identifies unclosed tags while isolating component instances. The addition of VOID_ELEMENTS and the instance-based tracking (tag-name-N) are clever solutions. The accompanying tests are thorough and cover the new logic and edge cases well. I have a few suggestions to improve the maintainability of the new, more complex parsing logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
42-167: 重构后的detectUnclosedTags逻辑清晰,能正确处理多实例场景。新实现有以下优点:
- 使用位置解析而非正则,更可靠地处理引号内的
>字符- 每个标签类型独立计数,生成唯一标识符(如
div-1、div-2)- 正确处理 void 元素、自闭合语法和大小写不敏感匹配
建议移除第 160 行的注释代码:
🔎 建议的修改
for (const tagNameLower of tagsToCheckLower) { if (openTagsStack[tagNameLower]) { for (const tagIndex of openTagsStack[tagNameLower]) { - // unclosedTags.add(`${tagNameLower}`); unclosedTags.add(`${tagNameLower}-${tagIndex}`); } } }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.tspackages/x-markdown/src/XMarkdown/core/Renderer.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
detectUnclosedTags(42-167)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
packages/x-markdown/src/XMarkdown/core/index.ts (1)
Renderer(4-4)
🪛 GitHub Actions: ✅ test
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts
[error] 1157-1157: TS1005: '}' expected.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Agent
- GitHub Check: build preview
- GitHub Check: size
🔇 Additional comments (7)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (3)
18-33: LGTM! 标准 HTML void 元素集合定义正确。该集合正确包含了所有 HTML5 规范中的 void 元素,用于正确处理
<img>等自闭合标签的流状态判断。
186-189: LGTM!tagIndexes机制正确隔离了组件实例的流状态。通过在
cidRef中维护tagIndexes映射,每个自定义组件实例现在独立跟踪其索引,与detectUnclosedTags生成的唯一标识符(tagName-index)正确匹配,解决了多个同名组件共享流状态的问题。DOM 遍历顺序(深度优先)与标签检测顺序一致,确保索引匹配正确。
Also applies to: 210-214
259-259: LGTM!cidRef初始化扩展正确。添加
tagIndexes: {}为每次processHtml调用提供独立的标签索引状态。packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (4)
73-89: 新增的 void 元素测试用例覆盖良好。测试正确验证了:
- 标准 void 元素语法
<img src="...">不被视为未闭合- 自闭合语法
<img src="..." />同样正确处理- 不完整的标签(缺少
>)被正确检测为未闭合修复上述语法错误后,这些测试将有效验证 void 元素的处理逻辑。
25-35: 测试期望已正确更新为后缀格式。更新后的断言(如
'custom-tag-1'、'tag-b-1')与Renderer.ts中新的按标签索引机制保持一致。Also applies to: 52-54
587-588: Mock 数据已正确更新为后缀格式。
mockUnclosedTags使用'streaming-tag-1'格式与新的标签索引机制匹配,确保streamStatus集成测试的有效性。
990-991: 所有 mock 未闭合标签集合已统一使用新的后缀命名格式。
unclosed tags scenarios测试中的 mock 数据(如'div-1'、'span-1'、'p-1'、'a-1')正确反映了新的按实例索引机制,能有效验证嵌套结构中各组件的streamStatus独立性。Also applies to: 1026-1027, 1063-1064, 1097-1098
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes two critical bugs in the XMarkdown component's streaming functionality:
- Void element handling: Corrects detection of void HTML elements (like
<img>) to prevent perpetual "loading" status - Component stream status isolation: Ensures multiple instances of the same custom component receive independent stream status tracking
Key Changes
- Replaced regex-based tag parsing with character-by-character scanning for more robust HTML parsing
- Added VOID_ELEMENTS constant containing all HTML5 void elements
- Implemented per-instance stream status tracking using indexed identifiers (
tag-1,tag-2, etc.)
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| packages/x-markdown/src/XMarkdown/core/Renderer.ts | Rewrote detectUnclosedTags method with manual parsing, added VOID_ELEMENTS set, modified stream status tracking to use indexed tag identifiers for per-instance isolation |
| packages/x-markdown/src/XMarkdown/test/Renderer.test.ts | Updated test assertions to expect indexed tag identifiers (tag-1, tag-2) instead of plain tag names, added void element test case |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
42-166:detectUnclosedTags实现功能正确但建议重构以提高可维护性。新的基于位置的解析器正确实现了所有关键特性:
- 大小写不敏感的标签匹配(第 46-48 行)
- 按出现次序生成唯一标识符(第 50-51、107-108 行)
- 空元素识别(第 138 行)
- 自闭合语法检测(第 118-121 行)
然而,之前的评审意见仍然有效:该方法的长度和复杂度已显著增加。
🔎 建议的重构
考虑将解析逻辑拆分为更小的辅助方法:
parseOpeningTag(...)- 提取开始标签的解析逻辑parseClosingTag(...)- 提取结束标签的解析逻辑- 将正则表达式
/\s/和/[a-zA-Z0-9-]/定义为类的静态只读属性这将简化主
while循环,提高代码的可读性和可测试性。基于之前的评审反馈,建议进行重构以提高可维护性。
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.tspackages/x-markdown/src/XMarkdown/core/Renderer.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
packages/x-markdown/src/XMarkdown/core/index.ts (1)
Renderer(4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: test
- GitHub Check: build preview
- GitHub Check: size
🔇 Additional comments (13)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (9)
12-36: 测试用例正确反映了新的标签索引逻辑。期望值已更新为使用带后缀的标识符(
custom-tag-1),这与 Renderer.ts 中新的detectUnclosedTags实现一致。测试正确验证了未闭合标签、已闭合标签和自闭合标签的行为。
38-55: 多标签场景的测试更新正确。测试正确验证了当一个标签已闭合(
tag-a)而另一个标签未闭合(tag-b)时,只有tag-b-1会出现在结果集中。这与新的按出现次序生成后缀标识的逻辑一致。
73-89: 优秀的空元素测试覆盖。这个新增的测试用例很好地验证了 PR 的核心修复:
- 正确处理标准 HTML 空元素语法(
<img src="...">)- 正确处理自闭合语法(
<img src="..." />)- 正确处理不完整的标签(
<img src="image.p)仍被标记为未闭合测试覆盖了空元素处理的关键场景。
444-474: 嵌套标签边界情况测试已正确更新。测试用例准确验证了:
- 内层标签未闭合时,只有
inner-tag-1被检测到- 外层标签未闭合时,只有
outer-tag-1被检测到这确保了新的解析器能够正确跟踪嵌套结构中的标签状态。
476-494: 大小写不敏感测试已正确更新。测试验证了标签名的大小写不敏感处理,期望值正确使用了小写的后缀标识符(
test-tag-1),与 Renderer.ts 中将标签名转换为小写的实现一致。
496-541: 属性和畸形 HTML 的边界测试已正确更新。这些测试用例覆盖了重要的边界情况:
- 带属性的标签(class、id 等)
- 畸形的闭合标签(缺少
>)- 多余的闭合标签
所有期望值都已更新为使用后缀标识符,确保解析器在各种边界条件下的正确性。
557-571: 关键测试:验证了同一标签多次出现的索引机制。此测试直接验证了 PR 的核心目标之一:当同一标签多次出现时,每个实例都有独立的索引(第二个未闭合的
custom-tag被标识为custom-tag-2)。这是实现多个自定义组件独立streamStatus的基础。
574-630:streamStatus集成测试已正确更新。Mock 已更新为使用后缀标识符(
streaming-tag-1),正确验证了:
- 未闭合标签的
streamStatus为'loading'- 已闭合标签的
streamStatus为'done'这确保了新的标签索引机制与流式渲染状态正确集成。
978-1117: 优秀的多组件独立streamStatus测试覆盖。这些测试用例直接解决了之前 Copilot 提出的测试覆盖缺口:验证同一 Markdown 块中的多个自定义组件接收独立的
streamStatus值。测试场景包括:
- 父标签未闭合、子标签已闭合:父组件
streamStatus: 'loading',子组件streamStatus: 'done'- 父标签已闭合、子标签未闭合:相反的状态分配
- 多层级多个未闭合标签:每个组件根据其自身的闭合状态接收正确的状态
所有 mock 都正确使用了后缀标识符(
div-1、span-1等),完美验证了 PR 的核心修复目标。基于之前的评审反馈,此部分测试覆盖了关键场景。
packages/x-markdown/src/XMarkdown/core/Renderer.ts (4)
18-33: 正确定义了 HTML5 空元素集合。
VOID_ELEMENTS静态集合包含了所有标准的 HTML5 空元素(area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr),这是正确处理自闭合标签的基础。实现为static readonly确保了性能和不可变性。
185-244: 关键修复:组件流式状态隔离实现。
createReplaceElement方法中的更新实现了 PR 的核心目标:
- 第 210 行:为每个自定义组件维护独立的索引计数器(
cidRef.tagIndexes[name])- 第 211-213 行:使用带索引的标识符(
${name}-${cidRef.tagIndexes[name]})来查询该特定实例的流式状态这确保了同一 Markdown 块中的多个相同类型组件不再共享单一的
streamStatus,每个实例根据其自身的闭合状态独立接收'loading'或'done'状态。
246-254:processChildren正确传播tagIndexes状态。方法签名更新以包含
tagIndexes(第 249 行),确保在处理嵌套子元素时标签索引状态能够正确传播。这对于维护跨整个组件树的一致索引至关重要。
256-267:processHtml正确初始化标签索引跟踪。第 258 行将
cidRef初始化为包含空的tagIndexes对象,为每次 HTML 处理提供了干净的起始状态。这确保了不同渲染调用之间的索引计数器不会相互干扰。
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1590 +/- ##
==========================================
+ Coverage 97.09% 97.13% +0.03%
==========================================
Files 140 140
Lines 4273 4323 +50
Branches 1203 1210 +7
==========================================
+ Hits 4149 4199 +50
Misses 122 122
Partials 2 2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Bundle ReportChanges will increase total bundle size by 855 bytes (0.05%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: x-markdown-array-pushAssets Changed:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
248-260: 考虑提取cidRef类型定义以提升可维护性。
cidRef参数类型{ current: number; tagIndexes: Record<string, number> }在多处重复定义。可以考虑将其提取为命名类型,提升代码可读性和一致性。🔎 建议的重构
+interface CidRef { + current: number; + tagIndexes: Record<string, number>; +} - private createReplaceElement( - unclosedTags: Set<string> | undefined, - cidRef: { current: number; tagIndexes: Record<string, number> }, - ) { + private createReplaceElement( + unclosedTags: Set<string> | undefined, + cidRef: CidRef, + ) { - private processChildren( - children: DOMNode[], - unclosedTags: Set<string> | undefined, - cidRef: { current: number; tagIndexes: Record<string, number> }, - ): ReactNode { + private processChildren( + children: DOMNode[], + unclosedTags: Set<string> | undefined, + cidRef: CidRef, + ): ReactNode {
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.tspackages/x-markdown/src/XMarkdown/core/Renderer.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
detectUnclosedTags(44-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build preview
- GitHub Check: test
- GitHub Check: size
🔇 Additional comments (7)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (3)
18-35: LGTM!静态常量定义清晰且完整。
VOID_ELEMENTS包含了所有 HTML5 规范中的空元素,WHITESPACE_REGEX和TAG_NAME_CHAR_REGEX遵循了之前评审中关于集中管理正则表达式的建议。
44-168: 实现逻辑正确,有效解决了 void 元素和多实例流状态问题。手动解析方式比正则更健壮,基于栈的追踪机制正确处理了嵌套标签。使用
tagname-index后缀格式使每个组件实例能独立追踪流状态,这正是 PR 描述中提到的核心修复。有一个小细节可以考虑:当前实现跳过了无效的标签语法(如
<后直接跟数字的情况),这是合理的容错行为。
211-215: 流状态独立追踪逻辑正确。通过
cidRef.tagIndexes为每种标签类型维护递增计数器,并使用${name}-${cidRef.tagIndexes[name]}格式查找未闭合状态,确保了同一 Markdown 块中多个相同组件实例能获得独立的streamStatus。这正是 PR 描述中要解决的核心问题。packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (4)
73-96: void 元素测试用例覆盖全面。测试覆盖了三种关键场景:
- 标准 void 元素形式 (
<img src="...">)- 自闭合形式 (
<img src="..." />)- 不完整的语法 (
<img src="image.p)这与 PR 描述中的修复内容完全对应。
1022-1055: 此测试有效验证了组件实例独立流状态的修复。通过模拟
span-1为未闭合状态,验证了父组件div获得done状态而子组件span获得loading状态。这正好覆盖了之前评审中提到的"同一 Markdown 块中多个自定义组件共享单一 streamStatus"的场景。
564-578: 多实例场景测试正确验证了索引机制。测试用例
<custom-tag>first</custom-tag><custom-tag>second验证了第一个标签闭合后,第二个未闭合标签被标识为custom-tag-2,确认了标签计数器的正确递增行为。
1-9: 测试文件更新完整,覆盖了 PR 修复的核心场景。测试用例已全面更新以适配新的后缀命名机制 (
tagname-index),涵盖了:
- void 元素处理
- 多实例独立流状态
- 嵌套结构
- 边界情况
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (1)
73-96: ✅ Void 元素测试覆盖全面,建议添加注释说明边缘情况。新增的 void 元素测试正确覆盖了 PR 目标中提到的三种形式(标准 HTML、自闭合、显式闭合)。测试逻辑准确。
建议改进:
- Line 88 的测试用例注释为 "Unclosed void element",但实际测试的是格式错误的标签(缺少
>)。建议添加注释说明这是在测试不完整/格式错误的标签解析。- Line 93 的 html3 包含未闭合的
<p>标签但预期 size 为 0。建议添加注释说明<p>未注册为组件因此不被跟踪。🔎 建议的注释改进
// Test case: Unclosed void element + // Note: This tests an incomplete/malformed tag (missing closing >) const html2 = '<img src="image.p'; const result2 = detectUnclosedTags(html2); expect(result2.has('img-1')).toBe(true); // Test case: Nested void elements + // Note: The unclosed <p> tag is not tracked because 'p' is not registered as a component const html3 = '<div><img src="image.png"></div><p>'; const result3 = detectUnclosedTags(html3); expect(result3.size).toBe(0);
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
detectUnclosedTags(44-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build preview
- GitHub Check: size
- GitHub Check: test
🔇 Additional comments (3)
packages/x-markdown/src/XMarkdown/__test__/Renderer.test.ts (3)
213-245: ✅ 完美响应了历史评审意见和 PR 目标!此测试直接验证了 PR 描述中的核心 bug 修复:"多个自定义组件在同一 Markdown 块内不再共享单个 streamStatus"。测试准确地覆盖了多个实例独立跟踪 streamStatus 的场景(第一个实例闭合为 'done',第二个未闭合为 'loading'),完全响应了历史评审评论中 Copilot 的要求。
247-347: ✅ 测试覆盖全面且质量高!这组扩展测试全面覆盖了多实例场景的各种复杂情况:
- 全部闭合的多实例
- 嵌套实例的独立状态跟踪
- 深度嵌套混合状态
- 不同组件类型交错
特别是 Line 283-286 正确地考虑了 React 的渲染顺序(children 先于 parent 创建),Lines 332-344 通过
domNode.name正确区分不同组件类型。测试逻辑严谨,边缘情况处理到位。
25-25: ✅ 后缀命名约定更新一致且正确。所有测试期望和 Mock 数据已正确更新为使用后缀标识符格式(如
custom-tag-1、img-1、streaming-tag-1),与 Renderer.ts 中的新实现完全对齐。命名规则一致:<tag-name-lowercase>-<occurrence-index>。特别注意 Line 713 正确使用了
custom-tag-2表示同一标签的第二次出现,这体现了对新命名规则的准确理解。Also applies to: 52-54, 607-609, 632-632, 652-652, 673-673, 713-713, 731-731, 1134-1134, 1170-1170, 1207-1207, 1241-1241
|
@kimteayon Just a friendly ping to see if you've had a chance to review this. Thanks! |
1. Update detectUnclosedTags to correctly handle void elements (e.g., img). 2. Refactor the renderer to ensure streamStatus is independent for custom component instances with the same name.
68160fd to
4707677
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (2)
82-92: 跨闭合标签场景的行为考虑当前实现使用栈来匹配开闭标签,但对于跨闭合场景(如
<a><b></a></b>),闭合标签会按 LIFO 顺序弹出同名标签的栈。这在 HTML 解析器的行为中是可接受的,但如果需要严格匹配,可以考虑验证闭合顺序。对于当前 streaming 状态检测的用例,此行为应该是正确的。
211-215: 考虑添加显式小写处理以提高代码健壮性代码当前工作正常,因为
html-react-parser的底层库htmlparser2会自动将所有标签名称规范化为小写。detectUnclosedTags存储的是小写键(如custom-tag-1),而domNode.name来自 html-react-parser,也始终是小写的。因此查找能够正确工作。不过,为了提高代码明确性和防守性,建议在
createReplaceElement中显式添加小写处理,避免对 html-react-parser 行为的隐式依赖:建议的优化
// Manage tag indexes for custom components used for streaming status determination - cidRef.tagIndexes[name] = (cidRef.tagIndexes[name] ?? 0) + 1; - const streamStatus = unclosedTags?.has(`${name}-${cidRef.tagIndexes[name]}`) + const nameLower = name.toLowerCase(); + cidRef.tagIndexes[nameLower] = (cidRef.tagIndexes[nameLower] ?? 0) + 1; + const streamStatus = unclosedTags?.has(`${nameLower}-${cidRef.tagIndexes[nameLower]}`) ? 'loading' : 'done';
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/x-markdown/src/XMarkdown/__tests__/Renderer.test.tspackages/x-markdown/src/XMarkdown/core/Renderer.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
packages/x-markdown/src/XMarkdown/core/index.ts (1)
Renderer(4-4)
packages/x-markdown/src/XMarkdown/__tests__/Renderer.test.ts (1)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (1)
detectUnclosedTags(44-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: test
- GitHub Check: build preview
- GitHub Check: size
🔇 Additional comments (9)
packages/x-markdown/src/XMarkdown/core/Renderer.ts (3)
18-35: LGTM!常量定义清晰且遵循了已建立的模式。VOID_ELEMENTS 集合包含了所有标准 HTML5 void 元素,这正确地解决了 void 元素处理的问题。
248-256: LGTM!
processChildren的类型签名正确更新以包含tagIndexes,确保cidRef在渲染过程中正确传递。
258-261: LGTM!
processHtml正确初始化了cidRef,包含空的tagIndexes对象。初始化逻辑清晰简洁。packages/x-markdown/src/XMarkdown/__tests__/Renderer.test.ts (6)
22-55: LGTM!测试用例已正确更新以使用新的带后缀的标签键(如
'custom-tag-1')和基于 size 的检查,与detectUnclosedTags的新实现保持一致。
73-96: LGTM!新增的 void 元素测试覆盖全面,包括:
- 标准 HTML void 形式
- 自闭合形式
- 不完整标签(缺少
>)- 嵌套在其他标签中的 void 元素
这些测试正确验证了 PR 目标中提到的 void 元素处理修复。
213-347: LGTM! 出色的测试覆盖新增的多实例测试非常全面,涵盖了:
- 同一组件的多个实例,部分关闭部分未关闭
- 嵌套实例(正确记录了子组件先处理的行为)
- 深度嵌套的混合状态
- 不同组件类型的交错使用
这些测试很好地验证了每个组件实例独立跟踪
streamStatus的新功能。
587-714: LGTM!边缘情况测试已正确更新以匹配新的命名约定。特别是第 713 行的测试
'custom-tag-2'正确验证了第二个实例被标记为未关闭的情况。
1121-1261: LGTM!未关闭标签场景测试已正确更新,mock 数据使用了新的带后缀的命名约定(如
'div-1'、'span-1')。测试覆盖了多种复杂场景,包括父标签未关闭、子标签未关闭、多级未关闭等情况。
731-732: LGTM!
streamStatus集成测试已正确更新以使用带后缀的标签键。

中文版模板 / Chinese template
🤔 This is a ...
🔗 Related Issues
💡 Background and Solution
Fixed stuck "loading" state for void elements:
detectUnclosedTagsnow correctly handles void elements (e.g., img). The parser now supports:Standard HTML:
<img src="...">(No end tag)Self-closing (XHTML/JSX style):
<img src="..." />Explicit closing (Non-standard):
<img src="..."></img>Fixed the bug where registering a custom img component resulted in a perpetual loading
streamStatusdue to the tag being perceived as unclosed.Fixed shared state for multiple components:
Resolved an issue in the renderer where multiple custom components within the same Markdown block shared a single
streamStatus.Status is now tracked independently per component instance.
Added related tests.
📝 Change Log
streamStatus, and correct the shared stream status for multiple component instances.streamStatus不正确的问题,并修正了多个组件实例共享流式状态的问题。Summary by CodeRabbit
发布说明
新功能
Bug修复
测试
✏️ Tip: You can customize this high-level summary in your review settings.