From 8a68e9c208e5eefec8127ce468a18c2f5455fcc6 Mon Sep 17 00:00:00 2001 From: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Date: Fri, 26 Sep 2025 10:21:30 +0800 Subject: [PATCH] perf: move structured render components (#5710) * perf: move structured render components * chore: remove useless code --- .../{ => StructureRender}/Divider.tsx | 0 .../Indicator.tsx} | 48 +-- .../codeBlock/{ => StructureRender}/Link.tsx | 0 .../codeBlock/{ => StructureRender}/Table.tsx | 11 +- .../{ => StructureRender}/TextBlock.tsx | 11 +- .../codeBlock/{ => StructureRender}/Tips.tsx | 9 +- .../codeBlock/StructureRender/index.tsx | 111 +++++ .../Markdown/img/EChartsCodeBlock.tsx | 397 ++++-------------- .../app/src/components/Markdown/index.tsx | 102 +---- projects/app/src/components/Markdown/utils.ts | 8 +- 10 files changed, 229 insertions(+), 468 deletions(-) rename projects/app/src/components/Markdown/codeBlock/{ => StructureRender}/Divider.tsx (100%) rename projects/app/src/components/Markdown/codeBlock/{IndicatorCard.tsx => StructureRender/Indicator.tsx} (56%) rename projects/app/src/components/Markdown/codeBlock/{ => StructureRender}/Link.tsx (100%) rename projects/app/src/components/Markdown/codeBlock/{ => StructureRender}/Table.tsx (93%) rename projects/app/src/components/Markdown/codeBlock/{ => StructureRender}/TextBlock.tsx (93%) rename projects/app/src/components/Markdown/codeBlock/{ => StructureRender}/Tips.tsx (78%) create mode 100644 projects/app/src/components/Markdown/codeBlock/StructureRender/index.tsx diff --git a/projects/app/src/components/Markdown/codeBlock/Divider.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/Divider.tsx similarity index 100% rename from projects/app/src/components/Markdown/codeBlock/Divider.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/Divider.tsx diff --git a/projects/app/src/components/Markdown/codeBlock/IndicatorCard.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/Indicator.tsx similarity index 56% rename from projects/app/src/components/Markdown/codeBlock/IndicatorCard.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/Indicator.tsx index 3e755a2a2..d15aceb73 100644 --- a/projects/app/src/components/Markdown/codeBlock/IndicatorCard.tsx +++ b/projects/app/src/components/Markdown/codeBlock/StructureRender/Indicator.tsx @@ -18,7 +18,7 @@ const IndicatorCard: React.FC = ({ dataList }) => { return ( {dataList.map((indicator, index) => ( - + = ({ dataList }) => { overflow="hidden" > {/* indicator name */} - - - {indicator.name} - - + + {indicator.name} + {/* indicator value and unit */} - - - {indicator.value || t('common:core.chat.indicator.no_data')} - - + + {indicator.value || t('common:core.chat.indicator.no_data')} + ))} diff --git a/projects/app/src/components/Markdown/codeBlock/Link.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/Link.tsx similarity index 100% rename from projects/app/src/components/Markdown/codeBlock/Link.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/Link.tsx diff --git a/projects/app/src/components/Markdown/codeBlock/Table.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/Table.tsx similarity index 93% rename from projects/app/src/components/Markdown/codeBlock/Table.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/Table.tsx index c27e92bf3..a2b13dcc0 100644 --- a/projects/app/src/components/Markdown/codeBlock/Table.tsx +++ b/projects/app/src/components/Markdown/codeBlock/StructureRender/Table.tsx @@ -4,26 +4,25 @@ import Icon from '@fastgpt/web/components/common/Icon'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { useSafeTranslation } from '@fastgpt/web/hooks/useSafeTranslation'; -const TableBlock: React.FC<{ code: string }> = ({ code }) => { +const TableBlock = ({ data }: { data: any }) => { const { t } = useSafeTranslation(); - const tableData = JSON.parse(code); const [currentPage, setCurrentPage] = useState(1); const [perPage, setPerPage] = useState(10); - const headers = Object.keys(tableData[0]); + const headers = Object.keys(data[0]); // calculate paginated data const { paginatedData, totalPages } = useMemo(() => { - const total = Math.ceil(tableData.length / perPage); + const total = Math.ceil(data.length / perPage); const startIndex = (currentPage - 1) * perPage; const endIndex = startIndex + perPage; - const paginated = tableData.slice(startIndex, endIndex); + const paginated = data.slice(startIndex, endIndex); return { paginatedData: paginated, totalPages: total }; - }, [tableData, currentPage, perPage]); + }, [data, currentPage, perPage]); const handlePrevPage = () => { setCurrentPage((prev) => Math.max(prev - 1, 1)); diff --git a/projects/app/src/components/Markdown/codeBlock/TextBlock.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/TextBlock.tsx similarity index 93% rename from projects/app/src/components/Markdown/codeBlock/TextBlock.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/TextBlock.tsx index 53f5fd448..e5bbc42b6 100644 --- a/projects/app/src/components/Markdown/codeBlock/TextBlock.tsx +++ b/projects/app/src/components/Markdown/codeBlock/StructureRender/TextBlock.tsx @@ -36,16 +36,15 @@ const TextBlock: React.FC<{ content: string }> = ({ content }) => { return ( = ({ content }) => { {hasNewlines && ( <> {!isExpanded && ( - + @@ -72,7 +71,7 @@ const TextBlock: React.FC<{ content: string }> = ({ content }) => { > {detail} - + diff --git a/projects/app/src/components/Markdown/codeBlock/Tips.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/Tips.tsx similarity index 78% rename from projects/app/src/components/Markdown/codeBlock/Tips.tsx rename to projects/app/src/components/Markdown/codeBlock/StructureRender/Tips.tsx index 8f85da3ce..b8bda5cf0 100644 --- a/projects/app/src/components/Markdown/codeBlock/Tips.tsx +++ b/projects/app/src/components/Markdown/codeBlock/StructureRender/Tips.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Text, Flex } from '@chakra-ui/react'; +import { Flex, Box } from '@chakra-ui/react'; import Icon from '@fastgpt/web/components/common/Icon'; interface TipsProps { @@ -12,7 +12,8 @@ const Tips: React.FC = ({ content, type = 'error' }) => { return ( = ({ content, type = 'error' }) => { h="20px" color={isError ? 'red.500' : 'yellow.500'} /> - + {content} - + ); }; diff --git a/projects/app/src/components/Markdown/codeBlock/StructureRender/index.tsx b/projects/app/src/components/Markdown/codeBlock/StructureRender/index.tsx new file mode 100644 index 000000000..a0411d9e1 --- /dev/null +++ b/projects/app/src/components/Markdown/codeBlock/StructureRender/index.tsx @@ -0,0 +1,111 @@ +import React, { useMemo } from 'react'; +import dynamic from 'next/dynamic'; + +const Table = dynamic(() => import('./Table'), { ssr: false }); +const Indicator = dynamic(() => import('./Indicator'), { ssr: false }); +const Link = dynamic(() => import('./Link'), { ssr: false }); +const Tips = dynamic(() => import('./Tips'), { ssr: false }); +const Divider = dynamic(() => import('./Divider'), { ssr: false }); +const TextBlock = dynamic(() => import('./TextBlock'), { ssr: false }); +const EChartsCodeBlock = dynamic(() => import('../../img/EChartsCodeBlock'), { ssr: false }); + +type RenderTypeEnum = { + table: 'TABLE'; + indicator: 'INDICATOR'; + link: 'LINK'; + error_tips: 'ERROR_TIPS'; + warning_tips: 'WARNING_TIPS'; + divider: 'DIVIDER'; + textblock: 'TEXTBLOCK'; + chart: 'CHART'; +}; + +type renderType = + | { + type: RenderTypeEnum['table']; + content: { + data: Array>; + }; + } + | { + type: RenderTypeEnum['indicator']; + content: { + dataList: { + name: string; + value: string | number; + }[]; + }; + } + | { + type: RenderTypeEnum['link']; + content: { text: string; url: string }; + } + | { + type: RenderTypeEnum['error_tips']; + content: string; + } + | { + type: RenderTypeEnum['warning_tips']; + content: string; + } + | { + type: RenderTypeEnum['divider']; + content: null; + } + | { + type: RenderTypeEnum['textblock']; + content: string; + } + | { + type: RenderTypeEnum['chart']; + content: { + chartStructInfo: any; + echartsData: any; + }; + }; + +// convert single item to Markdown +const StructureRender = ({ code }: { code: string }) => { + const jsonObjList: renderType[] | string = useMemo(() => { + try { + const jsonObj = JSON.parse(code); + if (Array.isArray(jsonObj)) { + return jsonObj; + } + return [jsonObj]; + } catch { + return code; + } + }, [code]); + + if (typeof jsonObjList === 'string') { + return String(code); + } + + return ( + <> + {jsonObjList.map((jsonObj, index) => { + const { type, content } = jsonObj; + if (type === 'TABLE') return
; + if (type === 'INDICATOR') + return ; + if (type === 'LINK') return ; + if (type === 'ERROR_TIPS') return ; + if (type === 'WARNING_TIPS') + return ; + if (type === 'DIVIDER') return ; + if (type === 'TEXTBLOCK') return ; + if (type === 'CHART') + return ( + + ); + return String(JSON.stringify(jsonObj)); + })} + + ); +}; + +export default StructureRender; diff --git a/projects/app/src/components/Markdown/img/EChartsCodeBlock.tsx b/projects/app/src/components/Markdown/img/EChartsCodeBlock.tsx index 41046d85e..71937441b 100644 --- a/projects/app/src/components/Markdown/img/EChartsCodeBlock.tsx +++ b/projects/app/src/components/Markdown/img/EChartsCodeBlock.tsx @@ -7,42 +7,18 @@ import { useMount } from 'ahooks'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useScreen } from '@fastgpt/web/hooks/useScreen'; -type EChartsGrid = { - top: string; - left: string; - bottom: string; - right: string; - containLabel: boolean; -}; - -type EChartsSeries = { - data: number[]; - name: string; - type: string; -}; - -type EChartsConfig = { - xAxis: { data: string[]; type: string }[]; - yAxis: { type: string }[]; - grid: EChartsGrid; - legend: { show: boolean }; - series: EChartsSeries[]; - tooltip: { trigger: string }; - dataZoom: unknown[]; -}; - -const EChartsCodeBlock = ({ code }: { code: string }) => { +const EChartsCodeBlock = ({ + code, + echartConfig +}: { + code?: string; + echartConfig?: echarts.EChartsOption; +}) => { const chartRef = useRef(null); const eChart = useRef(); const { isPc } = useSystem(); - const [option, setOption] = useState(); + const [option, setOption] = useState(); const [width, setWidth] = useState(400); - const [dataRange, setDataRange] = useState({ start: 0, end: 100 }); - const [totalDataLength, setTotalDataLength] = useState(0); - const [originalXData, setOriginalXData] = useState([]); - const [originalYData, setOriginalYData] = useState([]); - const dragStartTime = useRef(0); - const [isDragging, setIsDragging] = useState(false); const findMarkdownDom = useCallback(() => { if (!chartRef.current) return; @@ -59,176 +35,83 @@ const EChartsCodeBlock = ({ code }: { code: string }) => { return parent?.parentElement; }, [isPc]); - // filter data - const filterDataByRange = useCallback( - (originalXData: string[], originalYData: number[], range: { start: number; end: number }) => { - if (!originalXData.length || !originalYData.length) return { xData: [], yData: [] }; - - const totalLength = Math.min(originalXData.length, originalYData.length); - - const startIndex = Math.floor((range.start / 100) * totalLength); - const endIndex = Math.min(totalLength, Math.ceil((range.end / 100) * totalLength)); - - const actualEndIndex = Math.max(startIndex + 1, endIndex); - - // slice data - const filteredXData = originalXData.slice(startIndex, actualEndIndex); - const filteredYData = originalYData.slice(startIndex, actualEndIndex); - - return { xData: filteredXData, yData: filteredYData }; - }, - [] - ); - - // x and y data extraction - const extractXYData = useCallback((echartsConfig: EChartsConfig) => { - const emptyResult = { - xData: [] as string[], - yData: [] as number[], - chartContent: null as EChartsConfig | null - }; - - if (echartsConfig?.series?.length > 0 && echartsConfig?.xAxis?.length > 0) { - const series = echartsConfig.series[0]; - const xAxis = echartsConfig.xAxis[0]; - - return { - xData: xAxis.data || [], - yData: series.data || [], - chartContent: echartsConfig - }; - } - - return emptyResult; - }, []); - - // abstract chart render function - const createChartOption = useCallback( - (xData: string[], yData: number[], chartContent?: EChartsConfig | null) => { - if (chartContent) { - return { - ...chartContent, - xAxis: chartContent.xAxis.map((axis) => ({ - ...axis, - data: xData - })), - series: chartContent.series.map((series) => ({ - ...series, - data: yData - })) - }; - } - - // fallback to default config - return { - grid: { - bottom: '15%', - left: '5%', - right: '5%', - top: '10%', - containLabel: true - }, - xAxis: { - type: 'category', - data: xData, - boundaryGap: true, - axisTick: { - alignWithLabel: true, - interval: 0 - }, - axisLabel: { - interval: (() => { - const dataLength = xData.length; - if (dataLength <= 10) return 0; - if (dataLength <= 20) return 1; - if (dataLength <= 50) return Math.floor(dataLength / 10); - return Math.floor(dataLength / 15); - })(), - rotate: 45, - fontSize: 10, - formatter: (value: string) => { - return value && value.length > 20 ? `${value.substring(0, 20)}...` : value; - } - } - }, - yAxis: { - type: 'value', - scale: true - }, - series: [ - { - type: 'bar', - data: yData, - barCategoryGap: '20%', - itemStyle: { - borderRadius: [4, 4, 0, 0] - }, - name: 'Data' - } - ], - tooltip: { - trigger: 'axis', - formatter: function (params: Array<{ name: string; seriesName: string; value: number }>) { - if (Array.isArray(params) && params.length > 0) { - const param = params[0]; - return `${param.name}
${param.seriesName}: ${param.value}`; - } - return ''; - } - } - }; - }, - [] - ); - useMount(() => { // @ts-ignore import('echarts-gl'); }); - // generate and update chart option useLayoutEffect(() => { - try { - const rawConfig: EChartsConfig = json5.parse(code.trim()); - - const { xData, yData, chartContent } = extractXYData(rawConfig); - - if (xData.length === 0 || yData.length === 0) { - return; + const defaultOptions = { + xAxis: { + axisLabel: { + rotate: 45, + interval: 0 + } } + }; - setOriginalXData(xData); - setOriginalYData(yData); - setTotalDataLength(Math.min(xData.length, yData.length)); + const rawOption = (() => { + try { + return echartConfig ? echartConfig : (json5.parse(code!.trim()) as echarts.EChartsOption); + } catch { + return {}; + } + })(); - const { xData: filteredXData, yData: filteredYData } = filterDataByRange( - xData, - yData, - dataRange - ); + const xAxis = rawOption.xAxis; - const chartOption = createChartOption(filteredXData, filteredYData, chartContent); + if (Array.isArray(xAxis)) { + xAxis.forEach((item) => { + item.axisLabel = { + ...defaultOptions.xAxis.axisLabel, + ...item.axisLabel + }; + }); + } else if (xAxis) { + xAxis.axisLabel = { + ...defaultOptions.xAxis.axisLabel, + ...xAxis.axisLabel + }; + } - // Add toolbox for image saving - const RenderOption = { - ...chartOption, - toolbox: { - feature: { - saveAsImage: {} + const option = { + ...rawOption, + grid: { + left: '10%', // 左边距 + right: '5%', // 右边距 + top: '15%', // 顶边距 + bottom: '25%' // 底边距 + }, + dataZoom: [ + { + type: 'slider', + xAxisIndex: 0, + start: 0, + end: 100, + show: true, + realtime: true, // 实时渲染 + zoomLock: false + } + ], + toolbox: { + feature: { + saveAsImage: { + show: true } } - }; - - setOption(RenderOption as EChartsConfig); - - if (chartRef.current) { - if (!eChart.current) { - eChart.current = echarts.init(chartRef.current); - } - eChart.current.setOption(RenderOption); } - } catch (error) { - console.error('ECharts render failed:', error); + }; + setOption(option); + + if (!rawOption) return; + + if (chartRef.current) { + try { + eChart.current = echarts.init(chartRef.current); + eChart.current.setOption(option); + } catch (error) { + console.error('ECharts render failed:', error); + } } findMarkdownDom(); @@ -236,159 +119,25 @@ const EChartsCodeBlock = ({ code }: { code: string }) => { return () => { if (eChart.current) { eChart.current.dispose(); - eChart.current = undefined; } }; - }, [code, findMarkdownDom, filterDataByRange, dataRange, createChartOption, extractXYData]); + }, [code, echartConfig, findMarkdownDom]); const { screenWidth } = useScreen(); useEffect(() => { findMarkdownDom(); - }, [screenWidth, findMarkdownDom]); + }, [screenWidth]); useEffect(() => { eChart.current?.resize(); }, [width]); - // slider control - const handleRangeChange = useCallback((newRange: { start: number; end: number }) => { - setDataRange(newRange); - }, []); - // handle drag - const handleDrag = useCallback( - (type: 'left' | 'right' | 'range', e: React.MouseEvent) => { - e.preventDefault(); - - setIsDragging(false); - dragStartTime.current = Date.now(); - const startX = e.clientX; - const { start: startValue, end: endValue } = dataRange; - const rangeWidth = endValue - startValue; - - const handleMouseMove = (moveEvent: MouseEvent) => { - const deltaX = Math.abs(moveEvent.clientX - startX); - const timeDelta = Date.now() - dragStartTime.current; - - if (deltaX > 5 || timeDelta > 100) { - setIsDragging(true); - } - - const deltaPercent = ((moveEvent.clientX - startX) / Math.max(width, 400)) * 100; - - // drag handle - if (type === 'left') { - const newStart = Math.max(0, Math.min(startValue + deltaPercent, endValue)); - handleRangeChange({ start: newStart, end: endValue }); - } else if (type === 'right') { - const newEnd = Math.min(100, Math.max(endValue + deltaPercent, startValue)); - handleRangeChange({ start: startValue, end: newEnd }); - } else if (type === 'range') { - const newStart = Math.max(0, Math.min(startValue + deltaPercent, 100 - rangeWidth)); - handleRangeChange({ start: newStart, end: newStart + rangeWidth }); - } - }; - - const handleMouseUp = () => { - document.removeEventListener('mousemove', handleMouseMove); - document.removeEventListener('mouseup', handleMouseUp); - setTimeout(() => setIsDragging(false), 100); - }; - - document.addEventListener('mousemove', handleMouseMove); - document.addEventListener('mouseup', handleMouseUp); - }, - [dataRange, width, handleRangeChange] - ); - return ( {!option && ( )} - - {/* data range slider */} - {option && totalDataLength > 1 && ( - - { - if (!isDragging) { - const rect = e.currentTarget.getBoundingClientRect(); - const percentage = ((e.clientX - rect.left) / rect.width) * 100; - const halfWidth = 10; - - const newStart = Math.max(0, Math.min(percentage - halfWidth, 80)); - const newEnd = Math.min(100, Math.max(percentage + halfWidth, 20)); - handleRangeChange({ start: newStart, end: newEnd }); - } - }} - > - {/* data thumbnail */} - {originalYData.length > 0 && ( - - { - const maxVal = Math.max(...originalYData); - const minVal = Math.min(...originalYData); - const range = maxVal - minVal || 1; - - return originalYData - .map((value, index) => { - const x = (index / (originalYData.length - 1)) * (width - 8) + 4; - const y = 36 - ((value - minVal) / range) * 32; - return `${x},${y}`; - }) - .join(' '); - })()} - fill="none" - stroke="#93c5fd" - strokeWidth="1.5" - opacity="0.7" - /> - - )} - - {/* select area */} - handleDrag('range', e)} - /> - - {/* left and right drag handle */} - handleDrag('left', e)} - /> - handleDrag('right', e)} - /> - - - )} ); }; diff --git a/projects/app/src/components/Markdown/index.tsx b/projects/app/src/components/Markdown/index.tsx index ce0f1f082..0cd855b74 100644 --- a/projects/app/src/components/Markdown/index.tsx +++ b/projects/app/src/components/Markdown/index.tsx @@ -14,7 +14,7 @@ import styles from './index.module.scss'; import { Box } from '@chakra-ui/react'; import { useCreation } from 'ahooks'; import type { AProps } from './A'; -import { CodeClassNameEnum } from './utils'; +import { CodeClassNameEnum, mdTextFormat } from './utils'; import DomPurify from 'dompurify'; @@ -26,19 +26,12 @@ const IframeCodeBlock = dynamic(() => import('./codeBlock/Iframe'), { ssr: false const IframeHtmlCodeBlock = dynamic(() => import('./codeBlock/iframe-html'), { ssr: false }); const VideoBlock = dynamic(() => import('./codeBlock/Video'), { ssr: false }); const AudioBlock = dynamic(() => import('./codeBlock/Audio'), { ssr: false }); -const TableBlock = dynamic(() => import('./codeBlock/Table'), { ssr: false }); -const IndicatorCard = dynamic(() => import('./codeBlock/IndicatorCard'), { ssr: false }); -const LinkBlock = dynamic(() => import('./codeBlock/Link'), { ssr: false }); -const Tips = dynamic(() => import('./codeBlock/Tips'), { ssr: false }); -const Divider = dynamic(() => import('./codeBlock/Divider'), { ssr: false }); -const TextBlock = dynamic(() => import('./codeBlock/TextBlock'), { ssr: false }); +const StructureRender = dynamic(() => import('./codeBlock/StructureRender'), { ssr: false }); const ChatGuide = dynamic(() => import('./chat/Guide'), { ssr: false }); const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false }); const A = dynamic(() => import('./A'), { ssr: false }); -const formatCodeBlock = (lang: string, content: string) => `\`\`\`${lang}\n${content}\n\`\`\``; - type Props = { source?: string; showAnimation?: boolean; @@ -79,75 +72,11 @@ const MarkdownRender = ({ }; }, [chatAuthData, onOpenCiteModal, showAnimation]); - // convert single item to Markdown - const convertRenderBlockToMarkdown = useCallback((jsonContent: string): string => { - const converItem = (type: string, content: any) => { - switch (type) { - case 'TEXT': - return (typeof content === 'string' ? content : JSON.stringify(content)) + '\n\n'; - - case 'CHART': - return content?.hasChart && content?.echartsData - ? `\`\`\`echarts\n${JSON.stringify(content.echartsData, null, 2)}\n\`\`\`\n\n` - : ''; - - case 'TABLE': - return content?.data - ? `\`\`\`table\n${JSON.stringify(content.data, null, 2)}\n\`\`\`\n\n` - : ''; - - case 'INDICATOR': - return content?.dataList - ? `\`\`\`indicator\n${JSON.stringify(content.dataList, null, 2)}\n\`\`\`\n\n` - : ''; - - case 'LINK': - return content?.text && content?.url - ? `\`\`\`link\n${JSON.stringify(content, null, 2)}\n\`\`\`\n\n` - : ''; - - case 'ERROR_TIPS': - return content ? `\`\`\`error_tips\n${content}\n\`\`\`\n\n` : ''; - - case 'WARNING_TIPS': - return content ? `\`\`\`warning_tips\n${content}\n\`\`\`\n\n` : ''; - - case 'DIVIDER': - return `\`\`\`divider\n\n\`\`\`\n\n`; - - case 'TEXTBLOCK': - return content ? `\`\`\`textblock\n${content}\n\`\`\`\n\n` : ''; - - default: - return formatCodeBlock('json', jsonContent); - } - }; - try { - const jsonObj = JSON.parse(jsonContent); - if (Array.isArray(jsonObj)) { - return jsonObj.map((item) => converItem(item.type, item.content)).join(`\n\n`); - } else { - return converItem(jsonObj.type, jsonObj.content); - } - } catch { - return formatCodeBlock('json', jsonContent); - } - }, []); - const formatSource = useMemo(() => { if (showAnimation || forbidZhFormat) return source; - const result = source.replace(/```RENDER([\s\S]*?)```/g, (match, p1) => { - // p1: the content inside ```RENDER ... ``` - const cleanedContent = p1 - .replace(/^```[\s\S]*?(\n)?/, '') - .replace(/```$/, '') - .trim(); - return convertRenderBlockToMarkdown(cleanedContent); - }); - - return result; - }, [convertRenderBlockToMarkdown, forbidZhFormat, showAnimation, source]); + return mdTextFormat(source); + }, [forbidZhFormat, showAnimation, source]); const sanitizedSource = useMemo(() => { return DomPurify.sanitize(formatSource); @@ -238,28 +167,9 @@ function Code(e: any) { if (codeType === CodeClassNameEnum.audio) { return ; } - if (codeType === CodeClassNameEnum.table) { - return ; + if (codeType === CodeClassNameEnum.render) { + return ; } - if (codeType === CodeClassNameEnum.indicator) { - return ; - } - if (codeType === CodeClassNameEnum.link) { - return ; - } - if (codeType === CodeClassNameEnum.error_tips) { - return ; - } - if (codeType === CodeClassNameEnum.warning_tips) { - return ; - } - if (codeType === CodeClassNameEnum.divider) { - return ; - } - if (codeType === CodeClassNameEnum.textblock) { - return ; - } - return ( {children} diff --git a/projects/app/src/components/Markdown/utils.ts b/projects/app/src/components/Markdown/utils.ts index 686619677..cbe64a7f1 100644 --- a/projects/app/src/components/Markdown/utils.ts +++ b/projects/app/src/components/Markdown/utils.ts @@ -11,13 +11,7 @@ export enum CodeClassNameEnum { svg = 'svg', video = 'video', audio = 'audio', - table = 'table', - indicator = 'indicator', - link = 'link', - error_tips = 'error_tips', - warning_tips = 'warning_tips', - divider = 'divider', - textblock = 'textblock' + render = 'render' } export const mdTextFormat = (text: string) => {