diff --git a/src/renderer/src/components/MarkdownShadowDOMRenderer.tsx b/src/renderer/src/components/MarkdownShadowDOMRenderer.tsx new file mode 100644 index 00000000..9972d521 --- /dev/null +++ b/src/renderer/src/components/MarkdownShadowDOMRenderer.tsx @@ -0,0 +1,63 @@ +import { StyleProvider } from '@ant-design/cssinjs' +import React, { useEffect, useRef } from 'react' +import { createPortal } from 'react-dom' +import { StyleSheetManager } from 'styled-components' + +interface Props { + children: React.ReactNode +} + +const ShadowDOMRenderer: React.FC = ({ children }) => { + const hostRef = useRef(null) + const [shadowRoot, setShadowRoot] = React.useState(null) + + useEffect(() => { + const host = hostRef.current + if (!host) return + + // 创建 shadow root + const shadow = host.shadowRoot || host.attachShadow({ mode: 'open' }) + + // 获取原始样式表 + const markdownStyleSheet = Array.from(document.styleSheets).find((sheet) => { + try { + return Array.from(sheet.cssRules).some((rule: CSSRule) => { + return rule.cssText?.includes('.markdown') + }) + } catch { + return false + } + }) + + if (markdownStyleSheet) { + const style = document.createElement('style') + const cssRules = Array.from(markdownStyleSheet.cssRules) + .map((rule) => rule.cssText) + .join('\n') + + style.textContent = cssRules + shadow.appendChild(style) + } + + setShadowRoot(shadow) + }, []) + + if (!shadowRoot) { + return
+ } + + return ( +
+ {createPortal( + + + {children} + + , + shadowRoot + )} +
+ ) +} + +export default ShadowDOMRenderer diff --git a/src/renderer/src/pages/home/Markdown/Markdown.tsx b/src/renderer/src/pages/home/Markdown/Markdown.tsx index 9bed5e9d..6248c802 100644 --- a/src/renderer/src/pages/home/Markdown/Markdown.tsx +++ b/src/renderer/src/pages/home/Markdown/Markdown.tsx @@ -1,13 +1,14 @@ import 'katex/dist/katex.min.css' import 'katex/dist/contrib/copy-tex' +import MarkdownShadowDOMRenderer from '@renderer/components/MarkdownShadowDOMRenderer' import { useSettings } from '@renderer/hooks/useSettings' -import { Message } from '@renderer/types' +import type { Message } from '@renderer/types' import { escapeBrackets, removeSvgEmptyLines, withGeminiGrounding } from '@renderer/utils/formats' import { isEmpty } from 'lodash' -import { FC, useMemo } from 'react' +import { type FC, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import ReactMarkdown, { Components } from 'react-markdown' +import ReactMarkdown, { type Components } from 'react-markdown' import rehypeKatex from 'rehype-katex' // @ts-ignore next-line import rehypeMathjax from 'rehype-mathjax' @@ -52,11 +53,12 @@ const Markdown: FC = ({ message }) => { return (