forked from mxx1111/mdlook
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrender.ts
More file actions
124 lines (106 loc) · 3.31 KB
/
Copy pathrender.ts
File metadata and controls
124 lines (106 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { initRenderer } from '@md/core'
import { postProcessHtml, renderMarkdown } from '@/utils'
import { useCustomComponentStore } from './customComponent'
import { useThemeStore } from './theme'
import { useUIStore } from './ui'
/**
* 渲染 Store
* 负责 Markdown 渲染、HTML 输出、标题提取等
*/
export const useRenderStore = defineStore(`render`, () => {
// 输出的 HTML
const output = ref(``)
// 阅读时间统计
const readingTime = reactive({
chars: 0,
words: 0,
minutes: 0,
})
// 文章标题列表(用于生成目录)
const titleList = ref<{
url: string
title: string
level: number
}[]>([])
// 渲染器实例(延迟初始化)
let renderer: ReturnType<typeof initRenderer> | null = null
/**
* 初始化渲染器(新主题系统)
* 主题样式通过 useThemeStore().applyCurrentTheme() 注入到 <style> 标签
*/
const initRendererInstance = (options?: {
isMacCodeBlock?: boolean
isShowLineNumber?: boolean
}) => {
renderer = initRenderer(options || {})
return renderer
}
// 获取渲染器
const getRenderer = () => renderer
// 提取标题
const extractTitles = () => {
const div = document.createElement(`div`)
div.innerHTML = output.value
const list = div.querySelectorAll<HTMLElement>(`[data-heading]`)
titleList.value = []
let i = 0
for (const item of list) {
item.setAttribute(`id`, `${i}`)
titleList.value.push({
url: `#${i}`,
title: `${item.textContent}`,
level: Number(item.tagName.slice(1)),
})
i++
}
output.value = div.innerHTML
}
// 渲染内容
const render = (content: string, options?: { themeMode?: 'light' | 'dark' }) => {
const themeStore = useThemeStore()
const uiStore = useUIStore()
const componentStore = useCustomComponentStore()
const themeMode = options?.themeMode ?? (uiStore.isDark ? `dark` : `light`)
// 编辑器可能从 WYSIWYG 模式直接启动,此时 CodeMirror 不会负责初始化渲染器。
// 在模块内部兜底,避免调用方依赖组件挂载顺序。
if (!renderer) {
renderer = initRenderer({
isMacCodeBlock: themeStore.isMacCodeBlock,
isShowLineNumber: themeStore.isShowLineNumber,
})
}
// 重置渲染器配置
// 注意:isUseIndent 和 isUseJustify 通过 CSS 变量处理,不需要传递给渲染器
renderer.reset({
citeStatus: themeStore.isCiteStatus,
legend: themeStore.legend,
countStatus: themeStore.isCountStatus,
isMacCodeBlock: themeStore.isMacCodeBlock,
isShowLineNumber: themeStore.isShowLineNumber,
themeMode,
components: componentStore.registry,
})
// 渲染 Markdown
const { html: baseHtml, readingTime: readingTimeResult } = renderMarkdown(content, renderer)
// 更新统计信息
readingTime.chars = content.length
readingTime.words = readingTimeResult.words
readingTime.minutes = Math.ceil(readingTimeResult.minutes)
// 后处理 HTML
output.value = postProcessHtml(baseHtml, readingTimeResult, renderer)
// 提取标题
extractTitles()
return output.value
}
return {
// State
output,
readingTime,
titleList,
// Actions
initRendererInstance,
getRenderer,
render,
extractTitles,
}
})