-
Notifications
You must be signed in to change notification settings - Fork 581
fix(Chat): add markedOptions prop to TChatContent for custom markdown rendering (#6176) #6214
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: develop
Are you sure you want to change the base?
Conversation
… rendering (Tencent#6176) Co-authored-by: chensid <41440132+chensid@users.noreply.github.com>
Co-authored-by: chensid <41440132+chensid@users.noreply.github.com>
fix(Chat): add markedOptions prop to TChatContent for custom markdown rendering (Tencent#6176)
fix(Chat): add markedOptions prop to TChatContent for custom markdown rendering
TDesign Component Site Preview Open
|
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 a bug where custom markdown rendering options couldn't be passed to the TChatContent component. The solution adds a new markedOptions prop that accepts configuration for the Marked markdown parser, enabling users to customize rendering behavior such as code block formatting.
Key Changes:
- Added
markedOptionsprop toTChatContentcomponent for custom markdown rendering configuration - Refactored Marked instance creation into a factory function that merges default options with user-provided options
- Implemented reactivity using
refandwatchto handle dynamicmarkedOptionschanges
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| packages/pro-components/chat/type.ts | Added markedOptions prop definition to TdChatContentProps interface |
| packages/pro-components/chat/chat-content-props.ts | Added markedOptions prop declaration with Object type |
| packages/pro-components/chat/chat-content.tsx | Refactored Marked instance creation into factory function, added reactivity with watch, and imported MarkedExtension type |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| */ | ||
| content?: string; | ||
| /** | ||
| * 透传给 Marked 的参数,用于自定义 markdown 渲染 |
Copilot
AI
Nov 29, 2025
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.
[nitpick] The documentation comment is in Chinese but should also consider adding an English translation or example for broader accessibility. Additionally, the JSDoc could include more details about what options are supported. Consider:
/**
* 透传给 Marked 的参数,用于自定义 markdown 渲染
* Options passed to Marked instance for custom markdown rendering
* @see https://marked.js.org/using_advanced#extensions
*/| * 透传给 Marked 的参数,用于自定义 markdown 渲染 | |
| * 透传给 Marked 的参数,用于自定义 markdown 渲染 | |
| * Options passed to the Marked instance for custom markdown rendering. | |
| * See: https://marked.js.org/using_advanced#extensions |
| // Use ref to store marked instance and watch for changes | ||
| const markedRef = ref(createMarkedInstance(props.markedOptions)); | ||
|
|
||
| // Watch for changes in markedOptions and recreate the instance | ||
| watch( | ||
| () => props.markedOptions, | ||
| (newOptions) => { | ||
| markedRef.value = createMarkedInstance(newOptions); | ||
| }, | ||
| { deep: true }, | ||
| ); | ||
|
|
Copilot
AI
Nov 29, 2025
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.
Consider using a computed property instead of ref + watch for better reactivity and simpler code. The current approach creates a new Marked instance on every change, which could be expensive. A computed property would provide the same functionality more idiomatically:
const markedRef = computed(() => createMarkedInstance(props.markedOptions));Then update line 111 to:
return markedRef.value.parse(markdown);This eliminates the need for the watch block (lines 98-105) and ensures the Marked instance is only recreated when markedOptions actually changes, without needing { deep: true }.
| // Use ref to store marked instance and watch for changes | |
| const markedRef = ref(createMarkedInstance(props.markedOptions)); | |
| // Watch for changes in markedOptions and recreate the instance | |
| watch( | |
| () => props.markedOptions, | |
| (newOptions) => { | |
| markedRef.value = createMarkedInstance(newOptions); | |
| }, | |
| { deep: true }, | |
| ); | |
| // Use computed to create marked instance based on markedOptions | |
| const markedRef = computed(() => createMarkedInstance(props.markedOptions)); |
| }, | ||
| }), | ||
| { | ||
| // Create marked instance with default options |
Copilot
AI
Nov 29, 2025
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.
[nitpick] The comment "Create marked instance with default options" is slightly misleading since the function also accepts and applies user-provided markedOptions. Consider updating it to be more accurate:
// Create marked instance with default renderer and optional user overrides| // Create marked instance with default options | |
| // Create marked instance with default renderer and optional user overrides |
| /** | ||
| * 透传给 Marked 的参数,用于自定义 markdown 渲染 | ||
| */ | ||
| markedOptions?: Record<string, any>; |
Copilot
AI
Nov 29, 2025
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.
The type Record<string, any> is too loose and bypasses TypeScript's type checking. Since the code imports MarkedExtension from 'marked' in chat-content.tsx, consider using MarkedExtension as the type instead:
markedOptions?: MarkedExtension;This would provide better type safety and IDE autocomplete for users of the component. You'll need to add import { MarkedExtension } from 'marked'; to this file.
| markedOptions: { | ||
| type: Object as PropType<TdChatContentProps['markedOptions']>, |
Copilot
AI
Nov 29, 2025
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.
The prop type should use MarkedExtension instead of Record<string, any> for better type safety:
markedOptions: {
type: Object as PropType<MarkedExtension>,
},This requires importing MarkedExtension from 'marked'. This change would work together with updating the type definition in type.ts.
| }), | ||
| { | ||
| // Create marked instance with default options | ||
| const createMarkedInstance = (markedOptions?: Record<string, any>) => { |
Copilot
AI
Nov 29, 2025
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.
The parameter type annotation markedOptions?: Record<string, any> is inconsistent with the actual usage. Since the function casts it to MarkedExtension on line 89, the parameter should be typed as MarkedExtension for clarity:
const createMarkedInstance = (markedOptions?: MarkedExtension) => {This removes the need for the type cast on line 89 and provides better type safety.
commit: |

🤔 这个 PR 的性质是?
🔗 相关 Issue
#6176
💡 需求背景和解决方案
TChatContent组件的 markdown 渲染配置(如customRenderer)无法通过 props 传递生效,因为Marked实例在组件内部硬编码创建,不接受外部配置。解决方案:
markedOptionsprop,支持透传MarkedExtension配置Marked实例,在默认渲染器基础上应用用户配置markedOptions变化,动态重建实例用法:
📝 更新日志
tdesign-vue-next
@tdesign-vue-next/chat
markedOptions自定义 markdown 渲染配置不生效的问题 #6176@tdesign-vue-next/auto-import-resolver
☑️ 请求合并前的自查清单