From e2e458f2ea6c471a4b362d98008f05191c674e54 Mon Sep 17 00:00:00 2001 From: AmintaCCCP Date: Sun, 7 Jun 2026 21:10:03 +0800 Subject: [PATCH 1/3] fix: improve markdown code block rendering (#206) - Fix inline code vs code block detection logic * Add data-code-block marker from pre to code element * Support code blocks without language specification * Prevent misidentification of code blocks as inline code - Enhance code block CSS styles to prevent line wrapping * Add white-space: pre to maintain original layout * Add word-wrap: normal and word-break: normal * Ensure horizontal scrolling instead of wrapping - Fix code tag regex in translation mode * Support code tags with attributes like * Improve regex pattern to match all code tag variations Fixes #206 Co-Authored-By: Claude Opus 4.8 --- src/components/BilingualMarkdownRenderer.tsx | 3 ++- src/components/MarkdownRenderer.tsx | 12 ++++++++++-- src/index.css | 11 +++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/components/BilingualMarkdownRenderer.tsx b/src/components/BilingualMarkdownRenderer.tsx index e66caff2..80bdc2b3 100644 --- a/src/components/BilingualMarkdownRenderer.tsx +++ b/src/components/BilingualMarkdownRenderer.tsx @@ -234,7 +234,8 @@ const BilingualMarkdownRenderer = forwardRef([\s\S]*?)<\/code>/g; + // 修改正则以支持带属性的 code 标签(如 ) + const codeRegex = /]*)?>([\s\S]*?)<\/code>/g; let lastIndex = 0; let match: RegExpExecArray | null; while ((match = codeRegex.exec(translatedTexts[i])) !== null) { diff --git a/src/components/MarkdownRenderer.tsx b/src/components/MarkdownRenderer.tsx index 5ec1e271..6040a61c 100644 --- a/src/components/MarkdownRenderer.tsx +++ b/src/components/MarkdownRenderer.tsx @@ -860,7 +860,9 @@ const MarkdownRenderer: React.FC = memo(({ {children} ), code: ({ className, children, ...props }) => { - const isInline = !className; + // 检查 props 中是否有 'data-code-block' 标记(由 pre 组件添加) + const isCodeBlock = 'data-code-block' in props || !!className; + const isInline = !isCodeBlock; const match = /language-(\w+)/.exec(className || ''); const language = match ? match[1] : ''; @@ -874,7 +876,13 @@ const MarkdownRenderer: React.FC = memo(({ ); }, - pre: ({ children }) => <>{children}, + pre: ({ children }) => { + // 给 code 子元素添加标记,表明它是代码块而不是行内代码 + if (React.isValidElement(children) && children.type === 'code') { + return <>{React.cloneElement(children as React.ReactElement, { 'data-code-block': true })}; + } + return <>{children}; + }, blockquote: ({ children }) => (
{children} diff --git a/src/index.css b/src/index.css index 72f785bf..e19f9010 100644 --- a/src/index.css +++ b/src/index.css @@ -191,6 +191,13 @@ /* ========== Markdown Prose Component Styles ========== */ @layer components { + .prose pre { + overflow-x: auto; + white-space: pre; + word-wrap: normal; + word-break: normal; + } + .prose pre code { display: block; padding: 1rem; @@ -199,6 +206,10 @@ line-height: 1.5rem; tab-size: 2; -moz-tab-size: 2; + white-space: pre; + word-wrap: normal; + word-break: normal; + overflow-x: auto; } .prose :not(pre) > code { From c277a2ed2547ef956675a8f34362c1cb9dd04dba Mon Sep 17 00:00:00 2001 From: AmintaCCCP Date: Sun, 7 Jun 2026 21:17:43 +0800 Subject: [PATCH 2/3] fix: address CodeRabbit audit and ASCII art rendering - Replace deprecated word-wrap with overflow-wrap in CSS - Improve TypeScript type safety for React.cloneElement - Add styling for plain pre tags (ASCII art/character art) * Support pre tags without code child elements * Ensure proper display for character art and diagrams * Maintain white-space: pre to prevent line wrapping Co-Authored-By: Claude Opus 4.8 --- src/components/MarkdownRenderer.tsx | 2 +- src/index.css | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/MarkdownRenderer.tsx b/src/components/MarkdownRenderer.tsx index 6040a61c..1c5d3dc1 100644 --- a/src/components/MarkdownRenderer.tsx +++ b/src/components/MarkdownRenderer.tsx @@ -879,7 +879,7 @@ const MarkdownRenderer: React.FC = memo(({ pre: ({ children }) => { // 给 code 子元素添加标记,表明它是代码块而不是行内代码 if (React.isValidElement(children) && children.type === 'code') { - return <>{React.cloneElement(children as React.ReactElement, { 'data-code-block': true })}; + return <>{React.cloneElement(children as React.ReactElement>, { 'data-code-block': true })}; } return <>{children}; }, diff --git a/src/index.css b/src/index.css index e19f9010..1697c92e 100644 --- a/src/index.css +++ b/src/index.css @@ -194,7 +194,7 @@ .prose pre { overflow-x: auto; white-space: pre; - word-wrap: normal; + overflow-wrap: normal; word-break: normal; } @@ -207,11 +207,28 @@ tab-size: 2; -moz-tab-size: 2; white-space: pre; - word-wrap: normal; + overflow-wrap: normal; word-break: normal; overflow-x: auto; } + /* 纯 pre 标签样式(如字符画、ASCII art),不包含 code 子元素 */ + .prose pre:not(:has(code)) { + padding: 1rem; + background-color: #f8fafc; + border-radius: 0.5rem; + font-size: 0.875rem; + line-height: 1.5rem; + font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace; + border: 1px solid rgba(0, 0, 0, 0.06); + } + + .dark .prose pre:not(:has(code)) { + background-color: #1e293b; + border-color: rgba(255, 255, 255, 0.04); + color: #e6edf3; + } + .prose :not(pre) > code { background-color: #f3f4f6; padding: 0.125rem 0.375rem; From 8ae59e92f7b0fc36353b47a74cc24783e42760d6 Mon Sep 17 00:00:00 2001 From: AmintaCCCP Date: Sun, 7 Jun 2026 21:19:54 +0800 Subject: [PATCH 3/3] fix: preserve pre tag for ASCII art without code element - Keep pre tag when it doesn't contain code child element - Ensure ASCII art and character diagrams maintain their container - Previously the pre tag was stripped causing layout issues Co-Authored-By: Claude Opus 4.8 --- src/components/MarkdownRenderer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MarkdownRenderer.tsx b/src/components/MarkdownRenderer.tsx index 1c5d3dc1..0e1f61f4 100644 --- a/src/components/MarkdownRenderer.tsx +++ b/src/components/MarkdownRenderer.tsx @@ -881,7 +881,8 @@ const MarkdownRenderer: React.FC = memo(({ if (React.isValidElement(children) && children.type === 'code') { return <>{React.cloneElement(children as React.ReactElement>, { 'data-code-block': true })}; } - return <>{children}; + // 对于非 code 子元素(如 ASCII 字符画),保留 pre 标签 + return
{children}
; }, blockquote: ({ children }) => (