feat(report_agent): enhance markdown rendering for lists and improve formatting; support nested lists and clean up HTML output

This commit is contained in:
666ghj 2026-02-14 17:04:04 +08:00
parent 7601d78fd4
commit 709a0d7023
2 changed files with 89 additions and 14 deletions

View file

@ -1887,14 +1887,29 @@ const renderMarkdown = (content) => {
//
html = html.replace(/^> (.+)$/gm, '<blockquote class="md-quote">$1</blockquote>')
//
html = html.replace(/^- (.+)$/gm, '<li class="md-li">$1</li>')
html = html.replace(/(<li class="md-li">[\s\S]*?<\/li>)(\s*<li)/g, '$1$2')
html = html.replace(/(<li class="md-li">.*<\/li>)+/g, '<ul class="md-ul">$&</ul>')
//
html = html.replace(/^\d+\. (.+)$/gm, '<li class="md-oli">$1</li>')
html = html.replace(/(<li class="md-oli">.*<\/li>)+/g, '<ol class="md-ol">$&</ol>')
// -
html = html.replace(/^(\s*)- (.+)$/gm, (match, indent, text) => {
const level = Math.floor(indent.length / 2)
return `<li class="md-li" data-level="${level}">${text}</li>`
})
html = html.replace(/^(\s*)(\d+)\. (.+)$/gm, (match, indent, num, text) => {
const level = Math.floor(indent.length / 2)
return `<li class="md-oli" data-level="${level}">${text}</li>`
})
//
html = html.replace(/(<li class="md-li"[^>]*>.*?<\/li>\s*)+/g, '<ul class="md-ul">$&</ul>')
//
html = html.replace(/(<li class="md-oli"[^>]*>.*?<\/li>\s*)+/g, '<ol class="md-ol">$&</ol>')
//
html = html.replace(/<\/li>\s+<li/g, '</li><li')
//
html = html.replace(/<ul class="md-ul">\s+/g, '<ul class="md-ul">')
html = html.replace(/<ol class="md-ol">\s+/g, '<ol class="md-ol">')
//
html = html.replace(/\s+<\/ul>/g, '</ul>')
html = html.replace(/\s+<\/ol>/g, '</ol>')
//
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
@ -1917,7 +1932,40 @@ const renderMarkdown = (content) => {
html = html.replace(/(<\/h[2-5]>)<\/p>/g, '$1')
html = html.replace(/<p class="md-p">(<ul|<ol|<blockquote|<pre|<hr)/g, '$1')
html = html.replace(/(<\/ul>|<\/ol>|<\/blockquote>|<\/pre>)<\/p>/g, '$1')
// <br>
html = html.replace(/<br>\s*(<ul|<ol)/g, '$1')
html = html.replace(/(<\/ul>|<\/ol>)\s*<br>/g, '$1')
// <br>
html = html.replace(/(<br>\s*){2,}/g, '<br>')
// <br>
html = html.replace(/(<\/ol>|<\/ul>)<br>(<p|<div)/g, '$1$2')
// <ol>
const tokens = html.split(/(<ol class="md-ol">(?:<li class="md-oli"[^>]*>[\s\S]*?<\/li>)+<\/ol>)/g)
let olCounter = 0
let inSequence = false
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].startsWith('<ol class="md-ol">')) {
const liCount = (tokens[i].match(/<li class="md-oli"/g) || []).length
if (liCount === 1) {
olCounter++
if (olCounter > 1) {
tokens[i] = tokens[i].replace('<ol class="md-ol">', `<ol class="md-ol" start="${olCounter}">`)
}
inSequence = true
} else {
olCounter = 0
inSequence = false
}
} else if (inSequence) {
if (/<h[2-5]/.test(tokens[i])) {
olCounter = 0
inSequence = false
}
}
}
html = tokens.join('')
return html
}
@ -2462,12 +2510,13 @@ watch(() => props.reportId, (newId) => {
.generated-content :deep(.md-ul),
.generated-content :deep(.md-ol) {
padding-left: 20px;
margin-bottom: 1em;
padding-left: 24px;
margin: 12px 0;
}
.generated-content :deep(.md-li) {
margin-bottom: 0.5em;
.generated-content :deep(.md-li),
.generated-content :deep(.md-oli) {
margin: 6px 0;
}
.generated-content :deep(.md-quote) {

View file

@ -606,7 +606,33 @@ const renderMarkdown = (content) => {
html = html.replace(/(<br>\s*){2,}/g, '<br>')
// <br>
html = html.replace(/(<\/ol>|<\/ul>)<br>(<p|<div)/g, '$1$2')
// <ol>
const tokens = html.split(/(<ol class="md-ol">(?:<li class="md-oli"[^>]*>[\s\S]*?<\/li>)+<\/ol>)/g)
let olCounter = 0
let inSequence = false
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].startsWith('<ol class="md-ol">')) {
const liCount = (tokens[i].match(/<li class="md-oli"/g) || []).length
if (liCount === 1) {
olCounter++
if (olCounter > 1) {
tokens[i] = tokens[i].replace('<ol class="md-ol">', `<ol class="md-ol" start="${olCounter}">`)
}
inSequence = true
} else {
olCounter = 0
inSequence = false
}
} else if (inSequence) {
if (/<h[2-5]/.test(tokens[i])) {
olCounter = 0
inSequence = false
}
}
}
html = tokens.join('')
return html
}