From 8f10b9fb62bedecf3c6ea92d2636aa586a3bcf82 Mon Sep 17 00:00:00 2001 From: selfrelease Date: Wed, 15 Jul 2026 15:02:31 +0800 Subject: [PATCH] =?UTF-8?q?deploy:=202026-07-15=2015:02=20=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/web/static/index.html | 191 ++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 97 deletions(-) diff --git a/demo/web/static/index.html b/demo/web/static/index.html index b39b81d..38b6e88 100644 --- a/demo/web/static/index.html +++ b/demo/web/static/index.html @@ -1197,120 +1197,117 @@ async function generateParadigm() { } } -/** 轻量 Markdown 转 HTML 渲染器 */ +/** 轻量 Markdown 转 HTML 渲染器(支持标题、列表、子列表、引用、粗体、代码) */ function renderMarkdown(md) { if (!md) return ''; const lines = md.split('\n'); let html = ''; - let inList = false; - let inOrderedList = false; - for (let i = 0; i < lines.length; i++) { - let line = lines[i]; - // 标题 - if (/^### /.test(line)) { - if (inList) { html += ''; inList = false; } - if (inOrderedList) { html += ''; inOrderedList = false; } - html += `

${inlineMd(line.slice(4))}

`; - } else if (/^## /.test(line)) { - if (inList) { html += ''; inList = false; } - if (inOrderedList) { html += ''; inOrderedList = false; } - html += `

${inlineMd(line.slice(3))}

`; - } else if (/^# /.test(line)) { - if (inList) { html += ''; inList = false; } - if (inOrderedList) { html += ''; inOrderedList = false; } - html += `

${inlineMd(line.slice(2))}

`; - } else if (/^[-*] /.test(line)) { - if (!inList) { html += ''; inList = false; } - if (inOrderedList) { html += ''; inOrderedList = false; } - html += ''; - } else { - if (inList) { html += ''; inList = false; } - if (inOrderedList) { html += ''; inOrderedList = false; } - html += `

${inlineMd(line)}

`; + let i = 0; + /** 关闭所有打开的列表 */ + function closeLists(stack) { + while (stack.length) { + html += stack.pop() === 'ul' ? '' : ''; } } - if (inList) html += ''; - if (inOrderedList) html += ''; + const listStack = []; + while (i < lines.length) { + let line = lines[i]; + const trimmed = line.trimStart(); + const indent = line.length - trimmed.length; + // 空行 + if (trimmed === '') { + closeLists(listStack); + i++; + continue; + } + // 标题 + if (/^### /.test(trimmed)) { + closeLists(listStack); + html += `

${inlineMd(trimmed.slice(4))}

`; + i++; continue; + } else if (/^## /.test(trimmed)) { + closeLists(listStack); + html += `

${inlineMd(trimmed.slice(3))}

`; + i++; continue; + } else if (/^# /.test(trimmed)) { + closeLists(listStack); + html += `

${inlineMd(trimmed.slice(2))}

`; + i++; continue; + } + // 引用块 > + if (/^> /.test(trimmed)) { + closeLists(listStack); + const quoteLines = []; + while (i < lines.length && /^>\s?/.test(lines[i].trimStart())) { + quoteLines.push(lines[i].trimStart().replace(/^>\s?/, '')); + i++; + } + html += `
${inlineMd(quoteLines.join(' '))}
`; + continue; + } + // 有序列表 + if (/^\d+\. /.test(trimmed)) { + const level = Math.floor(indent / 2); + while (listStack.length > level) { + html += listStack.pop() === 'ul' ? '' : ''; + } + if (listStack.length === level) { + if (listStack[level - 1] !== 'ol') { + if (listStack.length) html += listStack.pop() === 'ul' ? '' : ''; + html += '
    '; + listStack.push('ol'); + } + } else { + html += '
      '; + listStack.push('ol'); + } + html += `
    1. ${inlineMd(trimmed.replace(/^\d+\. /, ''))}
    2. `; + i++; continue; + } + // 无序列表 + if (/^[-*] /.test(trimmed)) { + const level = Math.floor(indent / 2); + while (listStack.length > level) { + html += listStack.pop() === 'ul' ? '' : '
    '; + } + if (listStack.length === level) { + if (listStack[level - 1] !== 'ul') { + if (listStack.length) html += listStack.pop() === 'ul' ? '' : '
'; + html += '