-
-
Notifications
You must be signed in to change notification settings - Fork 44
[Fix] Replace koishi-plugin-markdown with custom markdown transformer #690
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
Conversation
…ormer - Add transformToMarkdown function in utils/koishi.ts using marked library - Refactor text renderer to use new transformer with platform support - Pass session to render options for platform-aware markdown rendering - Remove he dependency for HTML entity decoding - Simplify getRenderer to synchronous method
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Walkthrough将渲染器获取改为同步接口,向渲染选项注入 Changes
Sequence DiagramsequenceDiagram
participant Client as 客户端
participant Renderer as DefaultRenderer
participant TextRender as TextRenderer
participant Transform as transformToMarkdown
participant Marked as Marked
Client->>Renderer: 调用 renderMessage(context, options)
Renderer->>TextRender: render(message, mergedOptions)(mergedOptions 包含 session)
TextRender->>Transform: transformAndEscape(elements, platform)
Transform->>Marked: marked.parse(markdown)
Marked-->>Transform: tokens[]
Transform->>Transform: renderToken / render -> 生成 h() 节点
Transform-->>TextRender: 返回 h[] 虚拟节点
TextRender-->>Renderer: 返回渲染后的文本/节点
Renderer-->>Client: 平台感知的消息输出
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: Repository UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (1)📓 Common learnings🧬 Code graph analysis (1)packages/core/src/utils/koishi.ts (3)
🪛 GitHub Check: CodeFactorpackages/core/src/utils/koishi.ts[notice] 31-96: packages/core/src/utils/koishi.ts#L31-L96 ⏰ 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). (2)
🔇 Additional comments (3)
✏️ Tip: You can disable this entire section by setting 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 @dingyi222666, 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 overhauls the Markdown rendering mechanism to resolve existing display issues and introduce greater flexibility. By replacing an external library with a custom 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 refactors the message rendering pipeline by introducing a new transformToMarkdown utility in koishi.ts that leverages the marked library for markdown parsing, replacing the previous koishi-plugin-markdown dependency. The DefaultRenderer's getRenderer method is made synchronous, and rendering options now merge with defaults and include session information. The TextRenderer is updated to use the new transformToMarkdown function, passing platform information for platform-specific rendering. Review comments suggest further improvements to the renderToken function within the new markdown utility, specifically to correctly render blockquotes using h('quote'), clarify ambiguous fallback rendering by returning children directly, and enhance readability by using switch statements. Additionally, the render function is advised to use flatMap to properly handle renderToken potentially returning an array of elements.
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
🤖 Fix all issues with AI agents
In @packages/core/src/renders/text.ts:
- Around line 25-26: Remove the leftover debugging console.log statements that
print JSON.stringify(transformed) in the text rendering module; locate the
occurrences in packages/core/src/renders/text.ts (calls that reference the
transformed variable around the render/transform function) and delete those
console.log lines (both the one near the earlier log and the duplicate around
line 38) so production code no longer emits debug output or pays the
JSON.stringify cost.
🧹 Nitpick comments (3)
packages/core/src/utils/koishi.ts (2)
62-62: 未知 token 类型使用'?'作为元素类型可能导致渲染问题。当遇到未知的带有子节点的 token 类型时,返回
h('?', children)可能在某些平台上无法正确渲染。建议返回一个更安全的容器元素或直接返回子节点。💡 建议的修改
- return h('?', children) + return h('span', children)或者直接返回第一个子节点(如果只有一个)或包装成 fragment:
- return h('?', children) + return children.length === 1 ? children[0] : h('', children)
87-91: 建议显式返回null而非隐式undefined。当遇到
</img>闭合标签时,return隐式返回undefined。虽然后续filter(Boolean)会过滤掉,但显式返回null可以提高代码可读性。💡 建议的修改
if (cap[2] === 'img') { - if (cap[1]) return + if (cap[1]) return null const src = cap[3].match(/src="([^"]+)"/) if (src) return h.image(src[1]) }packages/core/src/renders/text.ts (1)
51-58: 平台参数传递正确,但默认值与 transformToMarkdown 不一致。
transformAndEscape默认平台为'sandbox',而transformToMarkdown默认为'onebot'。虽然调用链中options.session?.platform ?? 'sandbox'会覆盖,但建议保持一致性。
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/core/src/middlewares/chat/render_message.tspackages/core/src/render.tspackages/core/src/renders/text.tspackages/core/src/services/chat.tspackages/core/src/utils/koishi.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/core/src/utils/koishi.ts (1)
packages/core/src/utils/types.ts (1)
PromiseLikeDisposable(3-3)
🪛 GitHub Check: CodeFactor
packages/core/src/utils/koishi.ts
[notice] 31-96: packages/core/src/utils/koishi.ts#L31-L96
Complex Method
packages/core/src/renders/text.ts
[warning] 25-25: packages/core/src/renders/text.ts#L25
Replace "0·"+JSON.stringify(transformed))⏎ with '0·'·+·JSON.stringify(transformed)) (prettier/prettier)
[warning] 38-38: packages/core/src/renders/text.ts#L38
Replace "1·"+ with '1·'·+· (prettier/prettier)
⏰ 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). (2)
- GitHub Check: lint
- GitHub Check: build
🔇 Additional comments (7)
packages/core/src/utils/koishi.ts (2)
5-21: 自定义 del tokenizer 正确修复了单波浪号问题。正则表达式
^~~(?=\S)([\s\S]*?\S)~~要求双波浪号~~才会触发删除线解析,这正确解决了 issue #689 中单个~被错误渲染为删除线的问题。
101-124: transformToMarkdown 实现正确,支持字符串和模板字符串两种调用方式。函数正确处理了空值检查和模板字符串拼接逻辑,默认平台为
'onebot'符合项目需求。packages/core/src/services/chat.ts (1)
51-51: 导入路径调整正确。将
DefaultRenderer和Renderer从koishi-plugin-chatluna统一导入,符合模块组织规范。packages/core/src/middlewares/chat/render_message.ts (1)
14-17: 正确传递 session 到渲染选项。通过将
session添加到渲染选项中,使得下游的transformToMarkdown可以根据session.platform进行平台感知的渲染,这是修复 issue #689 跨平台 Markdown 渲染问题的关键改动。packages/core/src/renders/text.ts (1)
3-3: 导入新的 transformToMarkdown 函数。正确从
koishi-plugin-chatluna/utils/koishi导入自定义的 Markdown 转换函数,替代了原有的外部依赖。packages/core/src/render.ts (2)
55-61: 选项合并和渲染器获取逻辑正确。将
Object.assign移到获取渲染器之前确保了选项正确合并,同步获取渲染器简化了代码流程。
104-106: 无需担忧。当前代码中getRenderer方法没有证据表明曾为异步方法。全代码库中不存在对该方法使用await的调用模式,也没有找到任何异步版本的定义。该方法一直以来都是同步返回this.renderers[type],因此不存在破坏性变更。Likely an incorrect or invalid review comment.
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/core/src/renders/text.ts (1)
46-53: 建议添加空值检查以提高健壮性。根据
transformToMarkdown的实现(当source为 falsy 时返回空数组[]),当element.attrs['content']为undefined或空字符串时会返回空数组,这可能导致原本的文本节点被意外移除。♻️ 建议的改进
export function transformAndEscape(source: h[], platform: string = 'sandbox') { return source.flatMap((element) => { if (element.type === 'text') { + const content = element.attrs['content'] + if (!content) { + return element + } - const base = transformToMarkdown(element.attrs['content'], platform) + const base = transformToMarkdown(content, platform) return base } return element }) }packages/core/src/render.ts (1)
103-105: 建议添加渲染器存在性检查。
getRenderer直接返回this.renderers[type],如果传入无效的type,将返回undefined,后续调用currentRenderer.render()时会抛出运行时错误。♻️ 建议的改进
getRenderer(type: string) { - return this.renderers[type] + const renderer = this.renderers[type] + if (!renderer) { + throw new ChatLunaError( + ChatLunaErrorCode.RENDER_ERROR, + new Error(`Renderer '${type}' not found`) + ) + } + return renderer }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/core/src/render.tspackages/core/src/renders/text.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/core/src/renders/text.ts (3)
packages/core/src/renders/koishi-element.ts (1)
transformAndEscape(44-56)packages/core/src/renders/pure-text.ts (1)
transformAndEscape(58-62)packages/core/src/utils/koishi.ts (1)
transformToMarkdown(110-124)
⏰ 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). (2)
- GitHub Check: build
- GitHub Check: lint
🔇 Additional comments (3)
packages/core/src/renders/text.ts (2)
3-3: LGTM!导入
transformToMarkdown替代外部依赖,符合 PR 目标。
14-17: LGTM!平台参数传递逻辑正确,使用
options.session?.platform获取平台信息,回退到'sandbox'作为默认值。packages/core/src/render.ts (1)
55-61: LGTM!选项合并逻辑正确,使用
Object.assign({}, this.defaultOptions, options)确保默认值被正确继承且不会修改原对象。同步获取渲染器简化了代码流程。
Allow renderToken to return h[] for unknown token types, preventing wrapper elements and preserving children directly in output.
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 (2)
packages/core/src/utils/koishi.ts (2)
87-91: 隐式返回undefined应显式处理。当遇到闭合的
<img>标签时(cap[1]为真),函数隐式返回undefined。虽然render函数会通过.filter(Boolean)过滤掉,但显式返回更清晰。♻️ 建议修复
if (cap[2] === 'img') { - if (cap[1]) return + if (cap[1]) return null const src = cap[3].match(/src="([^"]+)"/) if (src) return h.image(src[1]) }
41-63: 可选:使用映射表降低圈复杂度。静态分析标记此函数过于复杂。可考虑将 token 类型映射到处理函数,提高可维护性:
♻️ 可选重构示例
const tokenHandlers: Record<string, (token: Token, children: h[], platform?: string) => h | h[]> = { paragraph: (_, children) => h('p', children), em: (_, children) => h('em', children), strong: (_, children) => h('strong', children), del: (_, children) => h('del', children), link: (token, children) => h('a', { href: token.href }, children), // ... 其他类型 } function renderToken(token: Token, platform?: string): h | h[] { // ... 获取 children const handler = tokenHandlers[token.type] if (handler) return handler(token, children, platform) // ... fallback 逻辑 }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/core/src/utils/koishi.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/core/src/utils/koishi.ts (1)
packages/core/src/utils/types.ts (1)
PromiseLikeDisposable(3-3)
🪛 GitHub Check: CodeFactor
packages/core/src/utils/koishi.ts
[notice] 31-96: packages/core/src/utils/koishi.ts#L31-L96
Complex Method
⏰ 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). (2)
- GitHub Check: build
- GitHub Check: lint
🔇 Additional comments (4)
packages/core/src/utils/koishi.ts (4)
5-21: 自定义删除线分词器实现正确。正则表达式
^~~(?=\S)([\s\S]*?\S)~~仅匹配双波浪线 (~~),解决了 issue #689 中单个~导致意外删除线的问题。使用this.lexer.inlineTokens解析嵌套内容也是正确的做法。
61-62: 展平未知 token 类型的子节点处理正确。根据 commit 信息,对于未知 token 类型直接返回 children 是预期行为,避免产生不必要的包装元素。
97-101: LGTM!
flatMap+filter(Boolean)的组合正确处理了renderToken返回h | h[]或 falsy 值的情况。
103-126: 函数签名和实现良好。两个重载提供了良好的类型支持,模板字面量的重组逻辑正确。对 falsy 输入的提前返回是合理的防御性编程。
- Remove li wrapper for list items on non-Discord platforms to fix rendering issues - Add Telegram platform support for code-block element type
This PR fixes Markdown output rendering issues by replacing the external
koishi-plugin-markdowndependency with a custom markdown transformer implementation.Bug Fixes
Other Changes
transformToMarkdownfunction inutils/koishi.tsusing themarkedlibrary with custom tokenizer for strikethroughhedependency for HTML entity decodinggetRendererto synchronous method