Commit 6fb110ed authored by 水玉婷's avatar 水玉婷
Browse files

feat:优化md渲染table中文本部分

parent 53a84388
...@@ -2,6 +2,35 @@ ...@@ -2,6 +2,35 @@
* Markdown模板工具类 * Markdown模板工具类
* 用于解析和渲染Markdown内容 * 用于解析和渲染Markdown内容
*/ */
/**
* 处理文本中的Markdown格式(粗体、斜体、删除线、行内代码、标题等)
* @param text 要处理的文本
* @returns 处理后的文本
*/
const processMarkdownFormat = (text: string): string => {
let processedText = text;
// 处理标题(支持1-6级)
processedText = processedText.replace(/^######\s+(.*)$/gim, '<h6>$1</h6>');
processedText = processedText.replace(/^#####\s+(.*)$/gim, '<h5>$1</h5>');
processedText = processedText.replace(/^####\s+(.*)$/gim, '<h4>$1</h4>');
processedText = processedText.replace(/^###\s+(.*)$/gim, '<h3>$1</h3>');
processedText = processedText.replace(/^##\s+(.*)$/gim, '<h2>$1</h2>');
processedText = processedText.replace(/^#\s+(.*)$/gim, '<h1>$1</h1>');
// 处理粗体和斜体
processedText = processedText.replace(/\*\*(.*?)\*\*/gim, '<strong>$1</strong>');
processedText = processedText.replace(/\*(.*?)\*/gim, '<em>$1</em>');
processedText = processedText.replace(/__(.*?)__/gim, '<strong>$1</strong>');
processedText = processedText.replace(/_(.*?)_/gim, '<em>$1</em>');
// 处理删除线
processedText = processedText.replace(/~~(.*?)~~/gim, '<del>$1</del>');
// 处理行内代码
processedText = processedText.replace(/`([^`]+)`/gim, '<code>$1</code>');
return processedText;
};
/** /**
* 生成完整的表格HTML * 生成完整的表格HTML
* @param header 表头 * @param header 表头
...@@ -16,7 +45,8 @@ const generateCompleteTable = (header: string[], alignments: string[], dataRows: ...@@ -16,7 +45,8 @@ const generateCompleteTable = (header: string[], alignments: string[], dataRows:
tableHtml += ' <thead>\n <tr>\n'; tableHtml += ' <thead>\n <tr>\n';
header.forEach((cell, index) => { header.forEach((cell, index) => {
const align = alignments[index] || 'left'; const align = alignments[index] || 'left';
tableHtml += ` <th style="text-align: ${align}; border: 1px solid #ddd; padding: 8px; background-color: #f5f5f5; font-weight: bold;">${cell}</th>\n`; const processedCell = processMarkdownFormat(cell);
tableHtml += ` <th style="text-align: ${align}; border: 1px solid #ddd; padding: 8px; background-color: #f5f5f5; font-weight: bold;">${processedCell}</th>\n`;
}); });
tableHtml += ' </tr>\n </thead>\n'; tableHtml += ' </tr>\n </thead>\n';
...@@ -27,7 +57,8 @@ const generateCompleteTable = (header: string[], alignments: string[], dataRows: ...@@ -27,7 +57,8 @@ const generateCompleteTable = (header: string[], alignments: string[], dataRows:
tableHtml += ' <tr>\n'; tableHtml += ' <tr>\n';
row.forEach((cell, index) => { row.forEach((cell, index) => {
const align = alignments[index] || 'left'; const align = alignments[index] || 'left';
tableHtml += ` <td style="text-align: ${align}; border: 1px solid #ddd; padding: 8px;">${cell}</td>\n`; const processedCell = processMarkdownFormat(cell);
tableHtml += ` <td style="text-align: ${align}; border: 1px solid #ddd; padding: 8px;">${processedCell}</td>\n`;
}); });
tableHtml += ' </tr>\n'; tableHtml += ' </tr>\n';
}); });
...@@ -57,6 +88,9 @@ export const parseMarkdown = (text: string): string => { ...@@ -57,6 +88,9 @@ export const parseMarkdown = (text: string): string => {
.replace(/"/g, '&quot;') .replace(/"/g, '&quot;')
.replace(/'/g, '&#x27;'); .replace(/'/g, '&#x27;');
// 处理基本的Markdown格式(在表格解析之前处理,确保表格单元格中的格式也能被处理)
text = processMarkdownFormat(text);
// 对于完整文本,使用简单的表格处理逻辑 // 对于完整文本,使用简单的表格处理逻辑
// 使用正则表达式处理表格,避免复杂的流式处理 // 使用正则表达式处理表格,避免复杂的流式处理
text = text.replace(/(\|[^\n]+\|(?:\r?\n|\r))+/g, (match) => { text = text.replace(/(\|[^\n]+\|(?:\r?\n|\r))+/g, (match) => {
...@@ -108,27 +142,12 @@ export const parseMarkdown = (text: string): string => { ...@@ -108,27 +142,12 @@ export const parseMarkdown = (text: string): string => {
} }
}); });
// 处理标题(支持1-6级) // 使用统一的Markdown格式处理函数处理基础格式(包括标题)
text = text.replace(/^######\s+(.*)$/gim, '<h6>$1</h6>'); text = processMarkdownFormat(text);
text = text.replace(/^#####\s+(.*)$/gim, '<h5>$1</h5>');
text = text.replace(/^####\s+(.*)$/gim, '<h4>$1</h4>');
text = text.replace(/^###\s+(.*)$/gim, '<h3>$1</h3>');
text = text.replace(/^##\s+(.*)$/gim, '<h2>$1</h2>');
text = text.replace(/^#\s+(.*)$/gim, '<h1>$1</h1>');
// 处理粗体和斜体
text = text.replace(/\*\*(.*?)\*\*/gim, '<strong>$1</strong>');
text = text.replace(/\*(.*?)\*/gim, '<em>$1</em>');
text = text.replace(/__(.*?)__/gim, '<strong>$1</strong>');
text = text.replace(/_(.*?)_/gim, '<em>$1</em>');
// 处理删除线
text = text.replace(/~~(.*?)~~/gim, '<del>$1</del>');
// 处理代码块(支持语言标识) // 处理代码块(支持语言标识)
text = text.replace(/```(\w+)?\n([\s\S]*?)```/gim, '<pre><code class="language-$1">$2</code></pre>'); text = text.replace(/```(\w+)?\n([\s\S]*?)```/gim, '<pre><code class="language-$1">$2</code></pre>');
text = text.replace(/```([\s\S]*?)```/gim, '<pre><code>$1</code></pre>'); text = text.replace(/```([\s\S]*?)```/gim, '<pre><code>$1</code></pre>');
text = text.replace(/`([^`]+)`/gim, '<code>$1</code>');
// 处理链接(支持相对路径和绝对路径) // 处理链接(支持相对路径和绝对路径)
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/gim, (match, text, url) => { text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/gim, (match, text, url) => {
...@@ -353,7 +372,10 @@ class StreamingTableProcessor { ...@@ -353,7 +372,10 @@ class StreamingTableProcessor {
try { try {
// 解析表头 // 解析表头
const headerRow = this.tableData[0]; const headerRow = this.tableData[0];
const headerCells = headerRow.split('|').slice(1, -1).map(cell => cell.trim()); const headerCells = headerRow.split('|').slice(1, -1).map(cell => {
// 对表头单元格进行Markdown格式处理
return processMarkdownFormat(cell.trim());
});
// 解析对齐方式(从第二行) // 解析对齐方式(从第二行)
let alignments: string[] = []; let alignments: string[] = [];
...@@ -384,7 +406,10 @@ class StreamingTableProcessor { ...@@ -384,7 +406,10 @@ class StreamingTableProcessor {
const dataRows: string[][] = []; const dataRows: string[][] = [];
for (let i = dataStartIndex; i < this.tableData.length; i++) { for (let i = dataStartIndex; i < this.tableData.length; i++) {
const row = this.tableData[i]; const row = this.tableData[i];
const cells = row.split('|').slice(1, -1).map(cell => cell.trim()); const cells = row.split('|').slice(1, -1).map(cell => {
// 对数据单元格进行Markdown格式处理
return processMarkdownFormat(cell.trim());
});
dataRows.push(cells); dataRows.push(cells);
} }
...@@ -436,9 +461,10 @@ export const processStreamingMarkdown = (text: string): string => { ...@@ -436,9 +461,10 @@ export const processStreamingMarkdown = (text: string): string => {
return ''; return '';
} }
// 如果表格处理器返回了完整表格,直接返回 // 如果表格处理器返回了完整表格,需要确保表格内容中的Markdown格式也被处理
if (result.includes('<table')) { if (result.includes('<table')) {
return result; // 对表格内容进行Markdown格式处理
return processMarkdownFormat(result);
} }
// 否则,处理其他Markdown语法 // 否则,处理其他Markdown语法
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment