diff --git a/apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx b/apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx index 8edc680a9..f3efd6236 100644 --- a/apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx +++ b/apps/ai-game-creator-shell/src/components/ChatMarkdownMessage/index.tsx @@ -1,5 +1,5 @@ import type { ErrorInfo, ReactNode } from 'react'; -import { Component } from 'react'; +import { Component, createContext, useContext } from 'react'; import ReactMarkdown, { type Components } from 'react-markdown'; import remarkGfm from 'remark-gfm'; @@ -44,6 +44,34 @@ class MarkdownErrorBoundary extends Component< } } +const ListDepthContext = createContext(0); + +function MarkdownUnorderedList({ children }: { children?: ReactNode }) { + const depth = useContext(ListDepthContext); + return ( + + + + ); +} + +function MarkdownOrderedList({ children }: { children?: ReactNode }) { + const depth = useContext(ListDepthContext); + return ( + +
    + {children} +
+
+ ); +} + const markdownComponents: Components = { // TODO: 产品确认安全外链策略后,再将链接文本恢复为可点击元素。 a: ({ children }) => children, @@ -60,14 +88,8 @@ const markdownComponents: Components = { p: ({ children }) => (

{children}

), - ul: ({ children }) => ( - - ), - ol: ({ children }) => ( -
    - {children} -
- ), + ul: MarkdownUnorderedList, + ol: MarkdownOrderedList, li: ({ children }) =>
  • - {children}
  • , blockquote: ({ children }) => (
    diff --git a/apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx b/apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx index d37929a32..f3778c4ab 100644 --- a/apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx +++ b/apps/ai-game-creator-shell/tests/ChatMarkdownMessage.test.tsx @@ -21,6 +21,23 @@ describe('ChatMarkdownMessage', () => { ); }); + it('为嵌套无序列表保留逐层缩进', () => { + const { container } = render( + , + ); + + const lists = container.querySelectorAll('ul'); + expect(lists).toHaveLength(3); + expect(lists[0]?.className).toContain('pl-0'); + expect(lists[1]?.className).toContain('pl-4'); + expect(lists[2]?.className).toContain('pl-4'); + }); + it('不会把 react-markdown 的 node 元数据泄漏到代码节点', () => { const { container } = render(