Skip to content

Commit 6b41e4e

Browse files
authored
🧨 feat: progressive for mermaid render (#47)
1 parent c163188 commit 6b41e4e

File tree

3 files changed

+17
-16
lines changed

3 files changed

+17
-16
lines changed

src/components/MarkdownPreview/index.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,16 @@ const showText = () => {
242242
// 若 reader 还没结束,则保持打字行为
243243
if (!readIsOver.value) {
244244
runReadBuffer()
245+
renderMermaidProcess()
245246
typingAnimationFrame = requestAnimationFrame(showText)
246247
} else {
247248
// 读取剩余的 buffer
248249
runReadBuffer(
249250
() => {
251+
renderMermaidProcess()
250252
typingAnimationFrame = requestAnimationFrame(showText)
251253
},
252254
() => {
253-
renderMermaidProcess()
254255
255256
window.$ModalNotification.success({
256257
title: '生成完毕',

src/components/MarkdownPreview/plugins/markdown.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ md.use(markdownItHighlight, {
2828

2929

3030
const transformMermaid = (content: string): string => {
31-
const mermaidBlockRegex = /^```mermaid\n([\s\S]*?)\n```$/gm
32-
return content.replace(mermaidBlockRegex, (match) => {
33-
return match
34-
})
31+
return content.replace(/(```mermaid)(?![^]*?```)/g, '```')
3532
}
3633

34+
3735
const transformMathMarkdown = (markdownText: string) => {
3836
const data = splitAtDelimiters(markdownText, [
3937
{

src/components/MarkdownPreview/plugins/mermaid.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ export const mermaidPlugin = (md, options = {}) => {
7878
if (cache.has(hash)) {
7979
svg = cache.get(hash)
8080
} else {
81-
// const { isValid } = await verifyMermaid(content)
8281

83-
// if (!isValid) {
84-
// return
85-
// }
82+
const { isValid } = await verifyMermaid(content)
83+
84+
if (!isValid) {
85+
cache.set(hash, content)
86+
container.dataset.mermaidStatus = 'error'
87+
container.innerHTML = `<pre>渲染失败:\n${ content }\n</pre>`
88+
return
89+
}
8690

8791
// 使用唯一 ID 渲染(避免图表冲突)
8892
const { svg: renderedSvg } = await mermaid.render(`mermaid-${ hash }`, content)
@@ -97,8 +101,9 @@ export const mermaidPlugin = (md, options = {}) => {
97101

98102
container.replaceWith(fragment)
99103
} catch (err) {
100-
// console.error('Mermaid 渲染失败:', err)
104+
console.error('Mermaid 渲染失败:', err)
101105
container.dataset.mermaidStatus = 'error'
106+
container.innerHTML = `<pre>渲染失败:\n${ content }\n</pre>`
102107
} finally {
103108
pendingQueue.delete(hash)
104109
}
@@ -107,8 +112,7 @@ export const mermaidPlugin = (md, options = {}) => {
107112
// 全局渲染控制器
108113
const processContainers = () => {
109114
const containers = document.querySelectorAll(`
110-
div[data-mermaid-status="pending"],
111-
div[data-mermaid-hash]:not([data-mermaid-status])
115+
div[data-mermaid-status="pending"]
112116
`) as NodeListOf<HTMLElement>
113117

114118

@@ -120,9 +124,7 @@ export const mermaidPlugin = (md, options = {}) => {
120124
if (container.dataset.mermaidStatus !== 'pending') {
121125
container.dataset.mermaidStatus = 'pending'
122126
}
123-
nextTick(() => {
124-
renderMermaid(container)
125-
})
127+
renderMermaid(container)
126128
})
127129
}
128130

@@ -137,7 +139,7 @@ export const mermaidPlugin = (md, options = {}) => {
137139

138140
// 触发 Mermaid 图表渲染 export
139141
processMermaid.fn = () => {
140-
processContainers()
142+
requestAnimationFrame(processContainers)
141143
}
142144
}
143145

0 commit comments

Comments
 (0)