diff --git a/src/renderer/src/assets/styles/markdown.scss b/src/renderer/src/assets/styles/markdown.scss index 1c6b4fea..84c15f72 100644 --- a/src/renderer/src/assets/styles/markdown.scss +++ b/src/renderer/src/assets/styles/markdown.scss @@ -94,14 +94,8 @@ background-color: var(--color-border); } - .katex-display { - span { - white-space: pre; - } - } - span { - white-space: pre-wrap; + white-space: pre; } p code, diff --git a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx index 63ff6fb3..63f6b1a2 100644 --- a/src/renderer/src/pages/home/Markdown/CodeBlock.tsx +++ b/src/renderer/src/pages/home/Markdown/CodeBlock.tsx @@ -8,6 +8,7 @@ import styled from 'styled-components' import Artifacts from './Artifacts' import Mermaid from './Mermaid' +import SvgPreview from './SvgPreview' interface CodeBlockProps { children: string @@ -79,8 +80,20 @@ const CodeBlock: React.FC = ({ children, className }) => { return } + if (language === 'svg') { + return ( + + + {''} + + + {children} + + ) + } + return match ? ( -
+
{codeCollapsible && shouldShowExpandButton && ( @@ -118,7 +131,7 @@ const CodeBlock: React.FC = ({ children, className }) => { )} {language === 'html' && children?.includes('') && } -
+
) : ( {children} ) @@ -142,6 +155,8 @@ const CopyButton: React.FC<{ text: string; style?: React.CSSProperties }> = ({ t ) } +const CodeBlockWrapper = styled.div`` + const CodeContent = styled.div<{ isShowLineNumbers: boolean }>` .shiki { padding: 1em; diff --git a/src/renderer/src/pages/home/Markdown/Markdown.tsx b/src/renderer/src/pages/home/Markdown/Markdown.tsx index 0448b94e..843e96c9 100644 --- a/src/renderer/src/pages/home/Markdown/Markdown.tsx +++ b/src/renderer/src/pages/home/Markdown/Markdown.tsx @@ -2,7 +2,7 @@ import 'katex/dist/katex.min.css' import { useSettings } from '@renderer/hooks/useSettings' import { Message } from '@renderer/types' -import { escapeBrackets } from '@renderer/utils/formula' +import { escapeBrackets, removeSvgEmptyLines } from '@renderer/utils/formula' import { isEmpty } from 'lodash' import { FC, useMemo } from 'react' import { useTranslation } from 'react-i18next' @@ -19,7 +19,7 @@ import ImagePreview from './ImagePreview' import Link from './Link' const ALLOWED_ELEMENTS = - /<(style|p|div|span|b|i|strong|em|ul|ol|li|table|tr|td|th|thead|tbody|h[1-6]|blockquote|pre|code|br|hr)/i + /<(style|p|div|span|b|i|strong|em|ul|ol|li|table|tr|td|th|thead|tbody|h[1-6]|blockquote|pre|code|br|hr|svg|path|circle|rect|line|polyline|polygon|text|g|defs|title|desc|tspan)/i interface Props { message: Message @@ -35,7 +35,7 @@ const Markdown: FC = ({ message }) => { const empty = isEmpty(message.content) const paused = message.status === 'paused' const content = empty && paused ? t('message.chat.completion.paused') : message.content - return escapeBrackets(content) + return removeSvgEmptyLines(escapeBrackets(content)) }, [message.content, message.status, t]) const rehypePlugins = useMemo(() => { @@ -52,7 +52,6 @@ const Markdown: FC = ({ message }) => { className="markdown" rehypePlugins={rehypePlugins} remarkPlugins={[remarkMath, remarkGfm]} - disallowedElements={mathEngine === 'KaTeX' ? ['style'] : []} components={ { a: Link, diff --git a/src/renderer/src/pages/home/Markdown/SvgPreview.tsx b/src/renderer/src/pages/home/Markdown/SvgPreview.tsx new file mode 100644 index 00000000..27685a4a --- /dev/null +++ b/src/renderer/src/pages/home/Markdown/SvgPreview.tsx @@ -0,0 +1,16 @@ +const SvgPreview = ({ children }: { children: string }) => { + return ( +
+ ) +} + +export default SvgPreview diff --git a/src/renderer/src/utils/formula.ts b/src/renderer/src/utils/formula.ts index f8d50b7c..ba39addc 100644 --- a/src/renderer/src/utils/formula.ts +++ b/src/renderer/src/utils/formula.ts @@ -43,3 +43,16 @@ export function extractTitle(html: string): string | null { return null } + +export function removeSvgEmptyLines(text: string): string { + // 用正则表达式匹配 标签内的内容 + const svgPattern = /()/g + + return text.replace(svgPattern, (svgMatch) => { + // 将 SVG 内容按行分割,过滤掉空行,然后重新组合 + return svgMatch + .split('\n') + .filter((line) => line.trim() !== '') + .join('\n') + }) +}