fix: markdown view \n do not work

This commit is contained in:
jialin
2025-08-13 19:50:54 +08:00
parent 0af8e34a8f
commit 2ca712435a
7 changed files with 37 additions and 13 deletions
+1
View File
@@ -68,6 +68,7 @@
"react-hotkeys-hook": "^4.5.0", "react-hotkeys-hook": "^4.5.0",
"react-markdown": "^9.0.3", "react-markdown": "^9.0.3",
"rehype-katex": "^7.0.1", "rehype-katex": "^7.0.1",
"remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"simplebar-react": "^3.2.6", "simplebar-react": "^3.2.6",
+18
View File
@@ -165,6 +165,9 @@ dependencies:
rehype-katex: rehype-katex:
specifier: ^7.0.1 specifier: ^7.0.1
version: 7.0.1 version: 7.0.1
remark-breaks:
specifier: ^4.0.0
version: 4.0.0
remark-gfm: remark-gfm:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.1 version: 4.0.1
@@ -13121,6 +13124,13 @@ packages:
- supports-color - supports-color
dev: false dev: false
/mdast-util-newline-to-break@2.0.0:
resolution: {integrity: sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==, tarball: https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz}
dependencies:
'@types/mdast': 4.0.4
mdast-util-find-and-replace: 3.0.2
dev: false
/mdast-util-phrasing@4.1.0: /mdast-util-phrasing@4.1.0:
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==, tarball: https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz} resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==, tarball: https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz}
dependencies: dependencies:
@@ -17456,6 +17466,14 @@ packages:
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
dev: false dev: false
/remark-breaks@4.0.0:
resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==, tarball: https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz}
dependencies:
'@types/mdast': 4.0.4
mdast-util-newline-to-break: 2.0.0
unified: 11.0.5
dev: false
/remark-gfm@4.0.1: /remark-gfm@4.0.1:
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==, tarball: https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz} resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==, tarball: https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz}
dependencies: dependencies:
@@ -255,7 +255,7 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
return () => { return () => {
chunkRequedtRef.current?.current?.abort?.(); chunkRequedtRef.current?.current?.abort?.();
}; };
}, [url]); }, [url, isDownloading]);
useEffect(() => { useEffect(() => {
debouncedScroll(); debouncedScroll();
@@ -357,4 +357,4 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
); );
}); });
export default React.memo(LogsViewer); export default LogsViewer;
@@ -3,6 +3,7 @@ import 'katex/dist/katex.min.css';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import rehypeKatex from 'rehype-katex'; import rehypeKatex from 'rehype-katex';
import remarkBreaks from 'remark-breaks';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math'; import remarkMath from 'remark-math';
import styled from 'styled-components'; import styled from 'styled-components';
@@ -17,9 +18,7 @@ interface FullMarkdownProps {
const Wrapper = styled.div.attrs(() => ({ const Wrapper = styled.div.attrs(() => ({
className: 'markdown-viewer' className: 'markdown-viewer'
}))` }))``;
line-height: 2;
`;
const CodeViewer = (props: any) => { const CodeViewer = (props: any) => {
const { children, className, node, theme, ...rest } = props; const { children, className, node, theme, ...rest } = props;
@@ -41,7 +40,7 @@ const FullMarkdown: React.FC<FullMarkdownProps> = ({ content, theme }) => {
return ( return (
<Wrapper> <Wrapper>
<ReactMarkdown <ReactMarkdown
remarkPlugins={[[remarkMath], remarkGfm]} remarkPlugins={[[remarkMath], remarkGfm, remarkBreaks]}
rehypePlugins={[rehypeKatex]} rehypePlugins={[rehypeKatex]}
components={{ components={{
code(props) { code(props) {
+1 -3
View File
@@ -1,6 +1,6 @@
.markdown-viewer { .markdown-viewer {
word-break: break-word; word-break: break-word;
white-space: pre-line; line-height: 2;
font-size: var(--font-size-base); font-size: var(--font-size-base);
.hr { .hr {
@@ -61,13 +61,11 @@
ul { ul {
margin-bottom: 0; margin-bottom: 0;
padding-left: 20px; padding-left: 20px;
line-height: 2;
} }
ol { ol {
margin-bottom: 0; margin-bottom: 0;
padding-left: 20px; padding-left: 20px;
line-height: 2;
} }
a * { a * {
@@ -877,6 +877,7 @@ const Models: React.FC<ModelsProps> = ({
onOk={handleCreateModel} onOk={handleCreateModel}
></DeployModal> ></DeployModal>
<ViewLogsModal <ViewLogsModal
status={currentInstance.status}
url={currentInstance.url} url={currentInstance.url}
tail={currentInstance.tail} tail={currentInstance.tail}
id={currentInstance.id} id={currentInstance.id}
@@ -12,15 +12,18 @@ type ViewModalProps = {
id?: number | string; id?: number | string;
modelId?: number | string; modelId?: number | string;
tail?: number; tail?: number;
status?: string;
onCancel: () => void; onCancel: () => void;
}; };
const ViewLogsModal: React.FC<ViewModalProps> = (props) => { const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const { setChunkRequest } = useSetChunkRequest(); const { setChunkRequest } = useSetChunkRequest();
const { open, url, onCancel, tail } = props || {}; const { open, url, onCancel, tail, status } = props || {};
const [enableScorllLoad, setEnableScorllLoad] = useState(true); const [enableScorllLoad, setEnableScorllLoad] = useState(true);
const [instanceState, setInstanceState] = useState<string>(''); const [isDownloading, setIsDownloading] = useState<boolean>(
status === InstanceStatusMap.Downloading
);
const logsViewerRef = React.useRef<any>(null); const logsViewerRef = React.useRef<any>(null);
const requestRef = React.useRef<any>(null); const requestRef = React.useRef<any>(null);
const contentRef = React.useRef<any>(null); const contentRef = React.useRef<any>(null);
@@ -33,8 +36,9 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
const updateHandler = (list: any) => { const updateHandler = (list: any) => {
const data = list?.find((item: any) => item.data?.id === props.id); const data = list?.find((item: any) => item.data?.id === props.id);
// state in InstanceRealtimeLogStatus will not enable scorll load, because it is in the trasisition state // state in InstanceRealtimeLogStatus will not enable scorll load, because it is in the trasisition state
if (data) { if (data) {
setInstanceState(data?.data?.state); setIsDownloading(data?.data?.state === InstanceStatusMap.Downloading);
setEnableScorllLoad( setEnableScorllLoad(
() => !InstanceRealtimeLogStatus.includes(data?.data?.state) () => !InstanceRealtimeLogStatus.includes(data?.data?.state)
); );
@@ -72,6 +76,9 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
url: `${MODELS_API}/${props.modelId}/instances`, url: `${MODELS_API}/${props.modelId}/instances`,
handler: updateHandler handler: updateHandler
}); });
} else {
logsViewerRef.current?.abort();
requestRef.current?.current?.cancel?.();
} }
return () => { return () => {
@@ -113,7 +120,7 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
url={url} url={url}
tail={tail} tail={tail}
enableScorllLoad={enableScorllLoad} enableScorllLoad={enableScorllLoad}
isDownloading={instanceState !== InstanceStatusMap.Downloading} isDownloading={isDownloading}
params={{ params={{
follow: true follow: true
}} }}