@sugarat/theme 0.2.16 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node.d.ts +60 -1
- package/node.js +21 -14
- package/package.json +3 -2
- package/src/components/BlogApp.vue +8 -4
- package/src/components/BlogBackToTop.vue +88 -0
- package/src/components/BlogComment.vue +92 -67
- package/src/components/BlogPopover.vue +33 -12
- package/src/composables/config/blog.ts +4 -0
- package/src/composables/config/index.ts +62 -1
- package/src/directives/index.ts +5 -0
- package/src/index.ts +7 -1
- package/src/utils/node/mdPlugins.ts +16 -59
- package/src/utils/node/vitePlugins.ts +2 -1
package/node.d.ts
CHANGED
|
@@ -92,6 +92,22 @@ declare namespace Theme {
|
|
|
92
92
|
label: string;
|
|
93
93
|
type: string;
|
|
94
94
|
}
|
|
95
|
+
interface CommentConfig extends GiscusConfig {
|
|
96
|
+
/**
|
|
97
|
+
* @default '评论'
|
|
98
|
+
*/
|
|
99
|
+
label?: string;
|
|
100
|
+
/**
|
|
101
|
+
* 自定义图标,SVG 格式
|
|
102
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
103
|
+
*/
|
|
104
|
+
icon?: string;
|
|
105
|
+
/**
|
|
106
|
+
* 移动端最小化按钮
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
mobileMinify?: boolean;
|
|
110
|
+
}
|
|
95
111
|
interface GiscusConfig {
|
|
96
112
|
repo: Repo;
|
|
97
113
|
repoId: string;
|
|
@@ -170,6 +186,9 @@ declare namespace Theme {
|
|
|
170
186
|
showIcon?: boolean;
|
|
171
187
|
html?: string;
|
|
172
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* 公告
|
|
191
|
+
*/
|
|
173
192
|
interface Popover {
|
|
174
193
|
title: string;
|
|
175
194
|
/**
|
|
@@ -178,12 +197,28 @@ declare namespace Theme {
|
|
|
178
197
|
* 配置改变时,会重新触发展示
|
|
179
198
|
*/
|
|
180
199
|
duration: number;
|
|
200
|
+
/**
|
|
201
|
+
* 移动端自动最小化
|
|
202
|
+
* @default false
|
|
203
|
+
*/
|
|
204
|
+
mobileMinify?: boolean;
|
|
181
205
|
body?: BlogPopover.Value[];
|
|
182
206
|
footer?: BlogPopover.Value[];
|
|
183
207
|
/**
|
|
184
208
|
* 手动重新打开
|
|
209
|
+
* @default true
|
|
185
210
|
*/
|
|
186
211
|
reopen?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* 设置展示图标,svg
|
|
214
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
215
|
+
*/
|
|
216
|
+
icon?: string;
|
|
217
|
+
/**
|
|
218
|
+
* 设置关闭图标,svg
|
|
219
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
220
|
+
*/
|
|
221
|
+
closeIcon?: string;
|
|
187
222
|
}
|
|
188
223
|
interface FriendLink {
|
|
189
224
|
nickname: string;
|
|
@@ -280,7 +315,7 @@ declare namespace Theme {
|
|
|
280
315
|
* 配置评论
|
|
281
316
|
* power by https://giscus.app/zh-CN
|
|
282
317
|
*/
|
|
283
|
-
comment?:
|
|
318
|
+
comment?: CommentConfig | false;
|
|
284
319
|
/**
|
|
285
320
|
* 阅读文章左侧的推荐文章(替代默认的sidebar)
|
|
286
321
|
*/
|
|
@@ -330,8 +365,32 @@ declare namespace Theme {
|
|
|
330
365
|
/**
|
|
331
366
|
* 配置内置的 markdown-it-task-checkbox 插件,设置 false 则关闭
|
|
332
367
|
* 详见 https://github.com/linsir/markdown-it-task-checkbox
|
|
368
|
+
* @default true
|
|
333
369
|
*/
|
|
334
370
|
taskCheckbox?: TaskCheckbox | boolean;
|
|
371
|
+
/**
|
|
372
|
+
* 支持 markdown 时间线语法,在 vitepress 中使用 markdown 渲染时间线(时间轴)样式。
|
|
373
|
+
* 详见 https://github.com/HanochMa/vitepress-markdown-timeline
|
|
374
|
+
* @default true
|
|
375
|
+
*/
|
|
376
|
+
timeline?: boolean;
|
|
377
|
+
/**
|
|
378
|
+
* 回到顶部
|
|
379
|
+
* @default true
|
|
380
|
+
*/
|
|
381
|
+
backToTop?: boolean | BackToTop;
|
|
382
|
+
}
|
|
383
|
+
interface BackToTop {
|
|
384
|
+
/**
|
|
385
|
+
* 距离顶部多少距离出现
|
|
386
|
+
* @default 450
|
|
387
|
+
*/
|
|
388
|
+
top?: number;
|
|
389
|
+
/**
|
|
390
|
+
* 设置展示图标,svg
|
|
391
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
392
|
+
*/
|
|
393
|
+
icon?: string;
|
|
335
394
|
}
|
|
336
395
|
interface TaskCheckbox {
|
|
337
396
|
disabled?: boolean;
|
package/node.js
CHANGED
|
@@ -36,7 +36,10 @@ __export(node_exports, {
|
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(node_exports);
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// src/utils/node/mdPlugins.ts
|
|
40
|
+
var import_module = require("module");
|
|
41
|
+
|
|
42
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.40_vue@3.3.4/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
40
43
|
var tabsMarker = "=tabs";
|
|
41
44
|
var tabsMarkerLen = tabsMarker.length;
|
|
42
45
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
|
@@ -200,6 +203,9 @@ var tabsPlugin = (md) => {
|
|
|
200
203
|
};
|
|
201
204
|
};
|
|
202
205
|
|
|
206
|
+
// src/utils/node/mdPlugins.ts
|
|
207
|
+
var import_vitepress_markdown_timeline = __toESM(require("vitepress-markdown-timeline"));
|
|
208
|
+
|
|
203
209
|
// src/utils/node/index.ts
|
|
204
210
|
var import_node_child_process = require("child_process");
|
|
205
211
|
var import_node_path = __toESM(require("path"));
|
|
@@ -312,29 +318,30 @@ function getFirstImagURLFromMD(content, route) {
|
|
|
312
318
|
}
|
|
313
319
|
|
|
314
320
|
// src/utils/node/mdPlugins.ts
|
|
321
|
+
var import_meta = {};
|
|
322
|
+
function _require(module2) {
|
|
323
|
+
return (typeof import_meta?.url !== "undefined" ? (0, import_module.createRequire)(import_meta.url) : require)(module2);
|
|
324
|
+
}
|
|
315
325
|
function getMarkdownPlugins(cfg) {
|
|
316
326
|
const markdownPlugin = [];
|
|
317
327
|
if (cfg?.tabs !== false) {
|
|
318
328
|
markdownPlugin.push(tabsPlugin);
|
|
319
329
|
}
|
|
320
|
-
if (cfg) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const { MermaidMarkdown } = require("vitepress-plugin-mermaid");
|
|
324
|
-
markdownPlugin.push(MermaidMarkdown);
|
|
325
|
-
}
|
|
330
|
+
if (cfg?.mermaid !== false) {
|
|
331
|
+
const { MermaidMarkdown } = _require("vitepress-plugin-mermaid");
|
|
332
|
+
markdownPlugin.push(MermaidMarkdown);
|
|
326
333
|
}
|
|
327
|
-
if (cfg) {
|
|
328
|
-
cfg
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
334
|
+
if (cfg.taskCheckbox !== false) {
|
|
335
|
+
markdownPlugin.push(taskCheckboxPlugin(typeof cfg?.taskCheckbox === "boolean" ? {} : cfg?.taskCheckbox));
|
|
336
|
+
}
|
|
337
|
+
if (cfg?.timeline !== false) {
|
|
338
|
+
markdownPlugin.push(import_vitepress_markdown_timeline.default);
|
|
332
339
|
}
|
|
333
340
|
return markdownPlugin;
|
|
334
341
|
}
|
|
335
342
|
function taskCheckboxPlugin(ops) {
|
|
336
343
|
return (md) => {
|
|
337
|
-
md.use(
|
|
344
|
+
md.use(_require("markdown-it-task-checkbox"), ops);
|
|
338
345
|
};
|
|
339
346
|
}
|
|
340
347
|
function registerMdPlugins(vpCfg, plugins) {
|
|
@@ -470,7 +477,7 @@ function getVitePlugins(cfg) {
|
|
|
470
477
|
);
|
|
471
478
|
}
|
|
472
479
|
if (cfg?.mermaid !== false) {
|
|
473
|
-
const { MermaidPlugin } =
|
|
480
|
+
const { MermaidPlugin } = _require("vitepress-plugin-mermaid");
|
|
474
481
|
plugins.push(MermaidPlugin(cfg?.mermaid === true ? {} : cfg?.mermaid ?? {}));
|
|
475
482
|
}
|
|
476
483
|
if (cfg?.RSS) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"gray-matter": "^4.0.3",
|
|
43
43
|
"markdown-it-task-checkbox": "^1.0.6",
|
|
44
44
|
"mermaid": "^10.2.4",
|
|
45
|
+
"vitepress-markdown-timeline": "^1.2.1",
|
|
45
46
|
"vitepress-plugin-mermaid": "2.0.13",
|
|
46
47
|
"vitepress-plugin-pagefind": "0.2.10",
|
|
47
48
|
"vitepress-plugin-rss": "0.2.1",
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"pagefind": "1.0.3",
|
|
57
58
|
"sass": "^1.56.1",
|
|
58
59
|
"typescript": "^4.8.2",
|
|
59
|
-
"vitepress": "1.0.0-rc.
|
|
60
|
+
"vitepress": "1.0.0-rc.40",
|
|
60
61
|
"vue": "^3.3.4"
|
|
61
62
|
},
|
|
62
63
|
"scripts": {
|
|
@@ -16,6 +16,7 @@ import BlogAlert from './BlogAlert.vue'
|
|
|
16
16
|
import BlogPopover from './BlogPopover.vue'
|
|
17
17
|
import BlogFooter from './BlogFooter.vue'
|
|
18
18
|
import BlogHomeHeaderAvatar from './BlogHomeHeaderAvatar.vue'
|
|
19
|
+
import BlogBackToTop from './BlogBackToTop.vue'
|
|
19
20
|
|
|
20
21
|
const { frontmatter } = useData()
|
|
21
22
|
const layout = computed(() => frontmatter.value.layout)
|
|
@@ -36,9 +37,9 @@ const { Layout } = Theme
|
|
|
36
37
|
<!-- 阅读时间分析 -->
|
|
37
38
|
<ClientOnly>
|
|
38
39
|
<BlogArticleAnalyze />
|
|
40
|
+
<!-- 图片预览 -->
|
|
41
|
+
<BlogImagePreview />
|
|
39
42
|
</ClientOnly>
|
|
40
|
-
<!-- 图片预览 -->
|
|
41
|
-
<BlogImagePreview />
|
|
42
43
|
</template>
|
|
43
44
|
|
|
44
45
|
<template #nav-bar-content-before>
|
|
@@ -66,10 +67,13 @@ const { Layout } = Theme
|
|
|
66
67
|
<slot name="sidebar-nav-after" />
|
|
67
68
|
<BlogSidebar />
|
|
68
69
|
</template>
|
|
69
|
-
<!-- 评论 -->
|
|
70
70
|
<template #doc-after>
|
|
71
71
|
<slot name="doc-after" />
|
|
72
|
-
|
|
72
|
+
<!-- 评论 -->
|
|
73
|
+
<ClientOnly>
|
|
74
|
+
<BlogBackToTop />
|
|
75
|
+
<BlogComment />
|
|
76
|
+
</ClientOnly>
|
|
73
77
|
</template>
|
|
74
78
|
<template #layout-bottom>
|
|
75
79
|
<BlogFooter v-if="layout === 'home'" />
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useElementSize, useScroll } from '@vueuse/core'
|
|
3
|
+
import { ElIcon } from 'element-plus'
|
|
4
|
+
import { computed, ref } from 'vue'
|
|
5
|
+
import { vOuterHtml } from '../directives'
|
|
6
|
+
import { useBackToTopConfig } from '../composables/config/blog'
|
|
7
|
+
|
|
8
|
+
function handleBackRoTop() {
|
|
9
|
+
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const $vpDoc = document.querySelector('.vp-doc')
|
|
13
|
+
const el = ref<any>($vpDoc)
|
|
14
|
+
const { width } = useElementSize(el)
|
|
15
|
+
const docWidth = computed(() => `${width.value}px`)
|
|
16
|
+
|
|
17
|
+
const backToTopConfig = useBackToTopConfig()
|
|
18
|
+
const open = computed(() => !!(backToTopConfig ?? true))
|
|
19
|
+
|
|
20
|
+
const { y } = useScroll(window)
|
|
21
|
+
const defaultTriggerHeight = 450
|
|
22
|
+
const triggerTop = computed(() => (typeof backToTopConfig === 'boolean' ? undefined : backToTopConfig?.top) ?? defaultTriggerHeight)
|
|
23
|
+
|
|
24
|
+
const show = computed(() => width && y.value > triggerTop.value)
|
|
25
|
+
|
|
26
|
+
const iconSVGStr = computed(() => typeof backToTopConfig === 'boolean' ? '' : backToTopConfig?.icon)
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<div v-if="open" v-show="show" class="back-to-top">
|
|
31
|
+
<span class="icon-wrapper" @click="handleBackRoTop">
|
|
32
|
+
<ElIcon :size="20">
|
|
33
|
+
<i v-if="iconSVGStr" v-outer-html="iconSVGStr" />
|
|
34
|
+
<svg v-else width="512" height="512" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
35
|
+
<path
|
|
36
|
+
fill="currentColor"
|
|
37
|
+
d="m20 22l-3.86-1.55c.7-1.53 1.2-3.11 1.51-4.72zM7.86 20.45L4 22l2.35-6.27c.31 1.61.81 3.19 1.51 4.72M12 2s5 2 5 10c0 3.1-.75 5.75-1.67 7.83A2 2 0 0 1 13.5 21h-3a2 2 0 0 1-1.83-1.17C7.76 17.75 7 15.1 7 12c0-8 5-10 5-10m0 10c1.1 0 2-.9 2-2s-.9-2-2-2s-2 .9-2 2s.9 2 2 2"
|
|
38
|
+
/>
|
|
39
|
+
</svg>
|
|
40
|
+
</ElIcon>
|
|
41
|
+
</span>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<style lang="scss" scoped>
|
|
46
|
+
.back-to-top {
|
|
47
|
+
position: fixed;
|
|
48
|
+
width: v-bind(docWidth);
|
|
49
|
+
text-align: right;
|
|
50
|
+
bottom: 80px;
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
transition: all 0.3s ease-in-out;
|
|
53
|
+
opacity: 0.6;
|
|
54
|
+
display: flex;
|
|
55
|
+
justify-content: right;
|
|
56
|
+
z-index: 200;
|
|
57
|
+
|
|
58
|
+
&:hover {
|
|
59
|
+
opacity: 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.icon-wrapper {
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
border-radius: 50%;
|
|
65
|
+
position: relative;
|
|
66
|
+
right: -80px;
|
|
67
|
+
background-color: var(--vp-c-bg);
|
|
68
|
+
box-shadow: var(--box-shadow);
|
|
69
|
+
padding: 4px;
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
background-color: var(--vp-c-brand-soft);
|
|
74
|
+
color: var(--vp-c-brand-1);
|
|
75
|
+
|
|
76
|
+
&:hover {
|
|
77
|
+
box-shadow: var(--box-shadow-hover);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media screen and (max-width: 1200px) {
|
|
83
|
+
.back-to-top .icon-wrapper {
|
|
84
|
+
border-radius: 50%;
|
|
85
|
+
position: static;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useElementVisibility } from '@vueuse/core'
|
|
2
|
+
import { useElementSize, useElementVisibility, useWindowSize } from '@vueuse/core'
|
|
3
3
|
import { useData, useRoute } from 'vitepress'
|
|
4
|
-
import { computed, ref, watch } from 'vue'
|
|
5
|
-
import {
|
|
4
|
+
import { computed, h, ref, watch } from 'vue'
|
|
5
|
+
import { ElIcon } from 'element-plus'
|
|
6
6
|
import { Comment } from '@element-plus/icons-vue'
|
|
7
7
|
import Giscus from '@giscus/vue'
|
|
8
8
|
import { useGiscusConfig } from '../composables/config/blog'
|
|
@@ -20,7 +20,7 @@ function handleScrollToComment() {
|
|
|
20
20
|
}
|
|
21
21
|
const giscusConfig = useGiscusConfig()
|
|
22
22
|
|
|
23
|
-
const commentConfig = computed<Theme.
|
|
23
|
+
const commentConfig = computed<Theme.CommentConfig>(() => {
|
|
24
24
|
if (!giscusConfig) {
|
|
25
25
|
return {} as any
|
|
26
26
|
}
|
|
@@ -58,87 +58,112 @@ watch(
|
|
|
58
58
|
immediate: true
|
|
59
59
|
}
|
|
60
60
|
)
|
|
61
|
+
|
|
62
|
+
const { width } = useWindowSize()
|
|
63
|
+
const mobileMinify = computed(() => width.value < 768 && (commentConfig.value.mobileMinify ?? true))
|
|
64
|
+
|
|
65
|
+
const CommentIcon = commentConfig.value?.icon
|
|
66
|
+
? h('i', {
|
|
67
|
+
onVnodeMounted(vnode) {
|
|
68
|
+
if (vnode.el) {
|
|
69
|
+
vnode.el.outerHTML = commentConfig.value?.icon
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
: h(Comment)
|
|
74
|
+
|
|
75
|
+
const $vpDoc = document.querySelector('.vp-doc')
|
|
76
|
+
const el = ref<any>($vpDoc)
|
|
77
|
+
const { width: _docWidth } = useElementSize(el)
|
|
78
|
+
const docWidth = computed(() => `${_docWidth.value}px`)
|
|
79
|
+
|
|
80
|
+
const labelText = computed(() => {
|
|
81
|
+
return commentConfig.value.label ?? '评论'
|
|
82
|
+
})
|
|
61
83
|
</script>
|
|
62
84
|
|
|
63
85
|
<template>
|
|
64
|
-
<div
|
|
65
|
-
v-if="show"
|
|
66
|
-
id="giscus-comment"
|
|
67
|
-
ref="commentEl"
|
|
68
|
-
class="comment"
|
|
69
|
-
data-pagefind-ignore="all"
|
|
70
|
-
>
|
|
71
|
-
<ElAffix
|
|
72
|
-
:class="{ hidden: commentIsVisible }"
|
|
73
|
-
class="comment-btn"
|
|
74
|
-
target="main"
|
|
75
|
-
position="bottom"
|
|
76
|
-
:offset="40"
|
|
77
|
-
>
|
|
78
|
-
<ElButton
|
|
79
|
-
plain
|
|
80
|
-
:icon="Comment"
|
|
81
|
-
type="primary"
|
|
82
|
-
@click="handleScrollToComment"
|
|
83
|
-
>
|
|
84
|
-
评论
|
|
85
|
-
</ElButton>
|
|
86
|
-
</ElAffix>
|
|
86
|
+
<div v-if="show && _docWidth" id="giscus-comment" ref="commentEl" class="comment" data-pagefind-ignore="all">
|
|
87
87
|
<Giscus
|
|
88
|
-
v-if="showComment"
|
|
89
|
-
:
|
|
90
|
-
:
|
|
91
|
-
:
|
|
92
|
-
:
|
|
93
|
-
:mapping="commentConfig.mapping || 'pathname'"
|
|
94
|
-
reactions-enabled="1"
|
|
95
|
-
emit-metadata="0"
|
|
96
|
-
:input-position="commentConfig.inputPosition || 'top'"
|
|
97
|
-
:theme="isDark ? 'dark' : 'light'"
|
|
98
|
-
:lang="commentConfig.lang || 'zh-CN'"
|
|
99
|
-
:loading="commentConfig.loading || 'eager'"
|
|
88
|
+
v-if="showComment" :repo="commentConfig.repo" :repo-id="commentConfig.repoId"
|
|
89
|
+
:category="commentConfig.category" :category-id="commentConfig.categoryId"
|
|
90
|
+
:mapping="commentConfig.mapping || 'pathname'" reactions-enabled="1" emit-metadata="0"
|
|
91
|
+
:input-position="commentConfig.inputPosition || 'top'" :theme="isDark ? 'dark' : 'light'"
|
|
92
|
+
:lang="commentConfig.lang || 'zh-CN'" :loading="commentConfig.loading || 'eager'"
|
|
100
93
|
/>
|
|
94
|
+
|
|
95
|
+
<div v-show="!commentIsVisible" class="comment-btn-wrapper">
|
|
96
|
+
<span v-if="!mobileMinify && labelText" class="icon-wrapper-text" @click="handleScrollToComment">
|
|
97
|
+
<ElIcon :size="20">
|
|
98
|
+
<CommentIcon />
|
|
99
|
+
</ElIcon>
|
|
100
|
+
<span class="text">
|
|
101
|
+
{{ labelText }}
|
|
102
|
+
</span>
|
|
103
|
+
</span>
|
|
104
|
+
<span v-else class="icon-wrapper" @click="handleScrollToComment">
|
|
105
|
+
<ElIcon :size="20">
|
|
106
|
+
<CommentIcon />
|
|
107
|
+
</ElIcon>
|
|
108
|
+
</span>
|
|
109
|
+
</div>
|
|
101
110
|
</div>
|
|
102
111
|
</template>
|
|
103
112
|
|
|
104
113
|
<style scoped lang="scss">
|
|
105
|
-
.comment {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
.comment-btn-wrapper {
|
|
115
|
+
position: fixed;
|
|
116
|
+
width: v-bind(docWidth);
|
|
117
|
+
text-align: right;
|
|
118
|
+
bottom: 40px;
|
|
119
|
+
font-size: 16px;
|
|
120
|
+
transition: all 0.3s ease-in-out;
|
|
121
|
+
opacity: 0.6;
|
|
122
|
+
display: flex;
|
|
123
|
+
justify-content: right;
|
|
124
|
+
z-index: 200;
|
|
125
|
+
|
|
126
|
+
&:hover {
|
|
127
|
+
opacity: 1;
|
|
113
128
|
}
|
|
114
|
-
|
|
129
|
+
|
|
130
|
+
.icon-wrapper,
|
|
131
|
+
.icon-wrapper-text {
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
border-radius: 50%;
|
|
134
|
+
position: relative;
|
|
135
|
+
right: -80px;
|
|
136
|
+
background-color: var(--vp-c-bg);
|
|
137
|
+
box-shadow: var(--box-shadow);
|
|
138
|
+
padding: 4px;
|
|
139
|
+
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
justify-content: center;
|
|
115
142
|
background-color: var(--vp-c-brand-soft);
|
|
116
|
-
|
|
117
|
-
|
|
143
|
+
color: var(--vp-c-brand-1);
|
|
144
|
+
|
|
145
|
+
&:hover {
|
|
146
|
+
box-shadow: var(--box-shadow-hover);
|
|
147
|
+
}
|
|
118
148
|
}
|
|
119
|
-
}
|
|
120
149
|
|
|
121
|
-
.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.el-button {
|
|
129
|
-
position: relative;
|
|
130
|
-
right: -100px;
|
|
150
|
+
.icon-wrapper-text {
|
|
151
|
+
border-radius: 2px;
|
|
152
|
+
padding: 2px 6px;
|
|
153
|
+
|
|
154
|
+
span.text{
|
|
155
|
+
font-size: 12px;
|
|
156
|
+
margin-left: 4px;
|
|
131
157
|
}
|
|
132
158
|
}
|
|
133
159
|
}
|
|
134
160
|
|
|
135
161
|
@media screen and (max-width: 1200px) {
|
|
136
|
-
.comment-btn {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
162
|
+
.comment-btn-wrapper {
|
|
163
|
+
|
|
164
|
+
.icon-wrapper,
|
|
165
|
+
.icon-wrapper-text {
|
|
166
|
+
position: static;
|
|
142
167
|
}
|
|
143
168
|
}
|
|
144
169
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { ElButton, ElIcon } from 'element-plus'
|
|
3
|
-
import { CircleCloseFilled
|
|
3
|
+
import { CircleCloseFilled } from '@element-plus/icons-vue'
|
|
4
4
|
import { computed, h, onMounted, ref } from 'vue'
|
|
5
5
|
import type { BlogPopover } from '@sugarat/theme'
|
|
6
6
|
import { parseStringStyle } from '@vue/shared'
|
|
7
|
+
import { useWindowSize } from '@vueuse/core'
|
|
7
8
|
import { useBlogConfig } from '../composables/config/blog'
|
|
9
|
+
import { vOuterHtml } from '../directives'
|
|
8
10
|
|
|
9
11
|
const { popover: popoverProps } = useBlogConfig()
|
|
10
12
|
|
|
@@ -20,6 +22,9 @@ const footerContent = computed(() => {
|
|
|
20
22
|
const storageKey = 'theme-blog-popover'
|
|
21
23
|
const closeFlag = `${storageKey}-close`
|
|
22
24
|
|
|
25
|
+
// 移动端最小化
|
|
26
|
+
const { width } = useWindowSize()
|
|
27
|
+
|
|
23
28
|
onMounted(() => {
|
|
24
29
|
if (!popoverProps?.title) {
|
|
25
30
|
return
|
|
@@ -30,6 +35,12 @@ onMounted(() => {
|
|
|
30
35
|
const newValue = JSON.stringify(popoverProps)
|
|
31
36
|
localStorage.setItem(storageKey, newValue)
|
|
32
37
|
|
|
38
|
+
// 移动端最小化
|
|
39
|
+
if (width.value < 768 && popoverProps?.mobileMinify) {
|
|
40
|
+
show.value = false
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
// >= 0 每次都展示,区别是否自动消失
|
|
34
45
|
if (Number(popoverProps?.duration ?? '') >= 0) {
|
|
35
46
|
show.value = true
|
|
@@ -117,12 +128,16 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
117
128
|
<div class="header">
|
|
118
129
|
<div class="title-wrapper">
|
|
119
130
|
<ElIcon size="20px">
|
|
120
|
-
<
|
|
131
|
+
<i v-if="popoverProps?.icon" v-outer-html="popoverProps.icon" />
|
|
132
|
+
<svg v-else width="512" height="512" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
|
133
|
+
<path fill="currentColor" d="M880 112c-3.8 0-7.7.7-11.6 2.3L292 345.9H128c-8.8 0-16 7.4-16 16.6v299c0 9.2 7.2 16.6 16 16.6h101.6c-3.7 11.6-5.6 23.9-5.6 36.4c0 65.9 53.8 119.5 120 119.5c55.4 0 102.1-37.6 115.9-88.4l408.6 164.2c3.9 1.5 7.8 2.3 11.6 2.3c16.9 0 32-14.2 32-33.2V145.2C912 126.2 897 112 880 112M344 762.3c-26.5 0-48-21.4-48-47.8c0-11.2 3.9-21.9 11-30.4l84.9 34.1c-2 24.6-22.7 44.1-47.9 44.1" />
|
|
134
|
+
</svg>
|
|
121
135
|
</ElIcon>
|
|
122
136
|
<span class="title">{{ popoverProps?.title }}</span>
|
|
123
137
|
</div>
|
|
124
138
|
<ElIcon class="close-icon" size="20px" @click="handleClose">
|
|
125
|
-
<
|
|
139
|
+
<i v-if="popoverProps?.closeIcon" v-outer-html="popoverProps.closeIcon" />
|
|
140
|
+
<CircleCloseFilled v-else />
|
|
126
141
|
</ElIcon>
|
|
127
142
|
</div>
|
|
128
143
|
<div v-if="bodyContent.length" class="body content">
|
|
@@ -138,12 +153,14 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
138
153
|
</div>
|
|
139
154
|
</div>
|
|
140
155
|
<div
|
|
141
|
-
v-show="!show && (popoverProps?.reopen ?? true) && popoverProps?.title"
|
|
142
|
-
class="theme-blog-popover-close"
|
|
156
|
+
v-show="!show && (popoverProps?.reopen ?? true) && popoverProps?.title" class="theme-blog-popover-close"
|
|
143
157
|
@click="show = true"
|
|
144
158
|
>
|
|
145
|
-
<ElIcon
|
|
146
|
-
<
|
|
159
|
+
<ElIcon>
|
|
160
|
+
<i v-if="popoverProps?.icon" v-outer-html="popoverProps.icon" />
|
|
161
|
+
<svg v-else width="512" height="512" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
|
162
|
+
<path fill="currentColor" d="M880 112c-3.8 0-7.7.7-11.6 2.3L292 345.9H128c-8.8 0-16 7.4-16 16.6v299c0 9.2 7.2 16.6 16 16.6h101.6c-3.7 11.6-5.6 23.9-5.6 36.4c0 65.9 53.8 119.5 120 119.5c55.4 0 102.1-37.6 115.9-88.4l408.6 164.2c3.9 1.5 7.8 2.3 11.6 2.3c16.9 0 32-14.2 32-33.2V145.2C912 126.2 897 112 880 112M344 762.3c-26.5 0-48-21.4-48-47.8c0-11.2 3.9-21.9 11-30.4l84.9 34.1c-2 24.6-22.7 44.1-47.9 44.1" />
|
|
163
|
+
</svg>
|
|
147
164
|
</ElIcon>
|
|
148
165
|
</div>
|
|
149
166
|
</template>
|
|
@@ -160,16 +177,13 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
160
177
|
border-radius: 6px;
|
|
161
178
|
background-color: rgba(var(--bg-gradient-home));
|
|
162
179
|
box-shadow: var(--box-shadow);
|
|
180
|
+
|
|
163
181
|
:deep(.el-button.el-button--primary) {
|
|
164
182
|
background-color: var(--vp-c-brand-2);
|
|
165
183
|
border-color: var(--vp-c-brand-2);
|
|
166
184
|
}
|
|
167
185
|
}
|
|
168
|
-
|
|
169
|
-
.theme-blog-popover {
|
|
170
|
-
top: 200px;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
186
|
+
|
|
173
187
|
.header {
|
|
174
188
|
background-color: var(--vp-c-brand-3);
|
|
175
189
|
color: #fff;
|
|
@@ -177,6 +191,7 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
177
191
|
display: flex;
|
|
178
192
|
justify-content: space-between;
|
|
179
193
|
align-items: center;
|
|
194
|
+
|
|
180
195
|
.close-icon {
|
|
181
196
|
cursor: pointer;
|
|
182
197
|
}
|
|
@@ -185,6 +200,7 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
185
200
|
.title-wrapper {
|
|
186
201
|
display: flex;
|
|
187
202
|
align-items: center;
|
|
203
|
+
|
|
188
204
|
.title {
|
|
189
205
|
font-size: 14px;
|
|
190
206
|
padding-left: 6px;
|
|
@@ -194,11 +210,13 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
194
210
|
.body {
|
|
195
211
|
box-sizing: border-box;
|
|
196
212
|
padding: 10px 10px 0;
|
|
213
|
+
|
|
197
214
|
hr {
|
|
198
215
|
border: none;
|
|
199
216
|
border-bottom: 1px solid #eaecef;
|
|
200
217
|
}
|
|
201
218
|
}
|
|
219
|
+
|
|
202
220
|
.footer {
|
|
203
221
|
box-sizing: border-box;
|
|
204
222
|
padding: 10px;
|
|
@@ -207,15 +225,18 @@ function PopoverValue(props: { key: number; item: BlogPopover.Value },
|
|
|
207
225
|
.body.content,
|
|
208
226
|
.footer.content {
|
|
209
227
|
text-align: center;
|
|
228
|
+
|
|
210
229
|
h4 {
|
|
211
230
|
text-align: center;
|
|
212
231
|
font-size: 12px;
|
|
213
232
|
}
|
|
233
|
+
|
|
214
234
|
p {
|
|
215
235
|
text-align: center;
|
|
216
236
|
padding: 10px 0;
|
|
217
237
|
font-size: 14px;
|
|
218
238
|
}
|
|
239
|
+
|
|
219
240
|
img {
|
|
220
241
|
width: 100%;
|
|
221
242
|
}
|
|
@@ -99,6 +99,22 @@ export namespace Theme {
|
|
|
99
99
|
type: string
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
export interface CommentConfig extends GiscusConfig {
|
|
103
|
+
/**
|
|
104
|
+
* @default '评论'
|
|
105
|
+
*/
|
|
106
|
+
label?: string
|
|
107
|
+
/**
|
|
108
|
+
* 自定义图标,SVG 格式
|
|
109
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
110
|
+
*/
|
|
111
|
+
icon?: string
|
|
112
|
+
/**
|
|
113
|
+
* 移动端最小化按钮
|
|
114
|
+
* @default true
|
|
115
|
+
*/
|
|
116
|
+
mobileMinify?: boolean
|
|
117
|
+
}
|
|
102
118
|
export interface GiscusConfig {
|
|
103
119
|
repo: Repo
|
|
104
120
|
repoId: string
|
|
@@ -181,6 +197,9 @@ export namespace Theme {
|
|
|
181
197
|
html?: string
|
|
182
198
|
}
|
|
183
199
|
|
|
200
|
+
/**
|
|
201
|
+
* 公告
|
|
202
|
+
*/
|
|
184
203
|
export interface Popover {
|
|
185
204
|
title: string
|
|
186
205
|
/**
|
|
@@ -189,12 +208,28 @@ export namespace Theme {
|
|
|
189
208
|
* 配置改变时,会重新触发展示
|
|
190
209
|
*/
|
|
191
210
|
duration: number
|
|
211
|
+
/**
|
|
212
|
+
* 移动端自动最小化
|
|
213
|
+
* @default false
|
|
214
|
+
*/
|
|
215
|
+
mobileMinify?: boolean
|
|
192
216
|
body?: BlogPopover.Value[]
|
|
193
217
|
footer?: BlogPopover.Value[]
|
|
194
218
|
/**
|
|
195
219
|
* 手动重新打开
|
|
220
|
+
* @default true
|
|
196
221
|
*/
|
|
197
222
|
reopen?: boolean
|
|
223
|
+
/**
|
|
224
|
+
* 设置展示图标,svg
|
|
225
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
226
|
+
*/
|
|
227
|
+
icon?: string
|
|
228
|
+
/**
|
|
229
|
+
* 设置关闭图标,svg
|
|
230
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
231
|
+
*/
|
|
232
|
+
closeIcon?: string
|
|
198
233
|
}
|
|
199
234
|
export interface FriendLink {
|
|
200
235
|
nickname: string
|
|
@@ -312,7 +347,7 @@ export namespace Theme {
|
|
|
312
347
|
* 配置评论
|
|
313
348
|
* power by https://giscus.app/zh-CN
|
|
314
349
|
*/
|
|
315
|
-
comment?:
|
|
350
|
+
comment?: CommentConfig | false
|
|
316
351
|
/**
|
|
317
352
|
* 阅读文章左侧的推荐文章(替代默认的sidebar)
|
|
318
353
|
*/
|
|
@@ -362,8 +397,34 @@ export namespace Theme {
|
|
|
362
397
|
/**
|
|
363
398
|
* 配置内置的 markdown-it-task-checkbox 插件,设置 false 则关闭
|
|
364
399
|
* 详见 https://github.com/linsir/markdown-it-task-checkbox
|
|
400
|
+
* @default true
|
|
365
401
|
*/
|
|
366
402
|
taskCheckbox?: TaskCheckbox | boolean
|
|
403
|
+
/**
|
|
404
|
+
* 支持 markdown 时间线语法,在 vitepress 中使用 markdown 渲染时间线(时间轴)样式。
|
|
405
|
+
* 详见 https://github.com/HanochMa/vitepress-markdown-timeline
|
|
406
|
+
* @default true
|
|
407
|
+
*/
|
|
408
|
+
timeline?: boolean
|
|
409
|
+
/**
|
|
410
|
+
* 回到顶部
|
|
411
|
+
* @default true
|
|
412
|
+
*/
|
|
413
|
+
backToTop?: boolean | BackToTop
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export interface BackToTop {
|
|
417
|
+
/**
|
|
418
|
+
* 距离顶部多少距离出现
|
|
419
|
+
* @default 450
|
|
420
|
+
*/
|
|
421
|
+
top?: number
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* 设置展示图标,svg
|
|
425
|
+
* @recommend https://iconbuddy.app/search?q=fire
|
|
426
|
+
*/
|
|
427
|
+
icon?: string
|
|
367
428
|
}
|
|
368
429
|
|
|
369
430
|
export interface TaskCheckbox {
|
package/src/index.ts
CHANGED
|
@@ -5,9 +5,14 @@ import './styles/index.scss'
|
|
|
5
5
|
import 'element-plus/dist/index.css'
|
|
6
6
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
|
7
7
|
|
|
8
|
+
// 引入时间线组件样式
|
|
9
|
+
import 'vitepress-markdown-timeline/dist/theme/index.css'
|
|
8
10
|
import type { Theme } from 'vitepress'
|
|
9
11
|
import DefaultTheme from 'vitepress/theme'
|
|
10
12
|
import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'
|
|
13
|
+
|
|
14
|
+
// 图表渲染组件
|
|
15
|
+
import Mermaid from 'vitepress-plugin-mermaid/Mermaid.vue'
|
|
11
16
|
import BlogApp from './components/BlogApp.vue'
|
|
12
17
|
import { withConfigProvider } from './composables/config/blog'
|
|
13
18
|
|
|
@@ -22,10 +27,11 @@ export const BlogTheme: Theme = {
|
|
|
22
27
|
...DefaultTheme,
|
|
23
28
|
Layout: withConfigProvider(BlogApp),
|
|
24
29
|
enhanceApp(ctx) {
|
|
25
|
-
enhanceAppWithTabs(ctx.app)
|
|
30
|
+
enhanceAppWithTabs(ctx.app as any)
|
|
26
31
|
DefaultTheme.enhanceApp(ctx)
|
|
27
32
|
ctx.app.component('TimelinePage', TimelinePage)
|
|
28
33
|
ctx.app.component('UserWorksPage', UserWorksPage)
|
|
34
|
+
ctx.app.component('Mermaid', Mermaid as any)
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/* eslint-disable global-require */
|
|
2
|
+
import { createRequire } from 'module'
|
|
2
3
|
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
|
3
4
|
import type { UserConfig } from 'vitepress'
|
|
5
|
+
import timeline from 'vitepress-markdown-timeline'
|
|
4
6
|
import type { Theme } from '../../composables/config/index'
|
|
5
7
|
import { aliasObjectToArray } from './index'
|
|
6
8
|
|
|
9
|
+
export function _require(module: any) {
|
|
10
|
+
return (typeof import.meta?.url !== 'undefined' ? createRequire(import.meta.url) : require)(module)
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
export function getMarkdownPlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
8
14
|
const markdownPlugin: any[] = []
|
|
9
15
|
// tabs支持,默认开启
|
|
@@ -12,27 +18,24 @@ export function getMarkdownPlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
// 添加mermaid markdown 插件
|
|
15
|
-
if (cfg) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const { MermaidMarkdown } = require('vitepress-plugin-mermaid')
|
|
19
|
-
markdownPlugin.push(MermaidMarkdown)
|
|
20
|
-
}
|
|
21
|
+
if (cfg?.mermaid !== false) {
|
|
22
|
+
const { MermaidMarkdown } = _require('vitepress-plugin-mermaid')
|
|
23
|
+
markdownPlugin.push(MermaidMarkdown)
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
if (cfg) {
|
|
24
|
-
cfg
|
|
25
|
-
if (cfg.taskCheckbox !== false) {
|
|
26
|
-
markdownPlugin.push(taskCheckboxPlugin(cfg.taskCheckbox))
|
|
27
|
-
}
|
|
26
|
+
if (cfg.taskCheckbox !== false) {
|
|
27
|
+
markdownPlugin.push(taskCheckboxPlugin(typeof cfg?.taskCheckbox === 'boolean' ? {} : cfg?.taskCheckbox))
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
if (cfg?.timeline !== false) {
|
|
31
|
+
markdownPlugin.push(timeline)
|
|
32
|
+
}
|
|
30
33
|
return markdownPlugin
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
export function taskCheckboxPlugin(ops
|
|
36
|
+
export function taskCheckboxPlugin(ops?: Theme.TaskCheckbox) {
|
|
34
37
|
return (md: any) => {
|
|
35
|
-
md.use(
|
|
38
|
+
md.use(_require('markdown-it-task-checkbox'), ops)
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -48,34 +51,6 @@ export function registerMdPlugins(vpCfg: any, plugins: any[]) {
|
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
/**
|
|
52
|
-
* 流程图支持,配置mermaid
|
|
53
|
-
*/
|
|
54
|
-
export function assignMermaid(config: any) {
|
|
55
|
-
if (!config?.mermaid)
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
if (!config.vite)
|
|
59
|
-
config.vite = {}
|
|
60
|
-
if (!config.vite.plugins)
|
|
61
|
-
config.vite.plugins = []
|
|
62
|
-
const { MermaidPlugin } = require('vitepress-plugin-mermaid')
|
|
63
|
-
config.vite.plugins.push(MermaidPlugin(config.mermaid))
|
|
64
|
-
if (!config.vite.resolve)
|
|
65
|
-
config.vite.resolve = {}
|
|
66
|
-
if (!config.vite.resolve.alias)
|
|
67
|
-
config.vite.resolve.alias = {}
|
|
68
|
-
|
|
69
|
-
config.vite.resolve.alias = [
|
|
70
|
-
...aliasObjectToArray({
|
|
71
|
-
...config.vite.resolve.alias,
|
|
72
|
-
'cytoscape/dist/cytoscape.umd.js': 'cytoscape/dist/cytoscape.esm.js',
|
|
73
|
-
'mermaid': 'mermaid/dist/mermaid.esm.mjs'
|
|
74
|
-
}),
|
|
75
|
-
{ find: /^dayjs\/(.*).js/, replacement: 'dayjs/esm/$1' }
|
|
76
|
-
]
|
|
77
|
-
}
|
|
78
|
-
|
|
79
54
|
export function patchMermaidPluginCfg(config: any) {
|
|
80
55
|
if (!config.vite.resolve)
|
|
81
56
|
config.vite.resolve = {}
|
|
@@ -100,24 +75,6 @@ export function patchOptimizeDeps(config: any) {
|
|
|
100
75
|
config.vite.optimizeDeps.include = ['element-plus']
|
|
101
76
|
}
|
|
102
77
|
|
|
103
|
-
export function wrapperCfgWithMermaid(config: UserConfig<Theme.Config>): any {
|
|
104
|
-
// @ts-expect-error
|
|
105
|
-
const extendThemeConfig = (config.extends?.themeConfig?.blog
|
|
106
|
-
|| {}) as Theme.BlogConfig
|
|
107
|
-
|
|
108
|
-
// 开关支持Mermaid
|
|
109
|
-
const resultConfig
|
|
110
|
-
= extendThemeConfig.mermaid === false
|
|
111
|
-
? config
|
|
112
|
-
: {
|
|
113
|
-
...config,
|
|
114
|
-
mermaid:
|
|
115
|
-
extendThemeConfig.mermaid === true ? {} : extendThemeConfig.mermaid
|
|
116
|
-
}
|
|
117
|
-
assignMermaid(resultConfig)
|
|
118
|
-
return resultConfig
|
|
119
|
-
}
|
|
120
|
-
|
|
121
78
|
export function supportRunExtendsPlugin(config: UserConfig<Theme.Config>) {
|
|
122
79
|
// 处理markdown插件
|
|
123
80
|
if (!config.markdown)
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from 'vitepress-plugin-pagefind'
|
|
12
12
|
import { RssPlugin } from 'vitepress-plugin-rss'
|
|
13
13
|
import type { Theme } from '../../composables/config/index'
|
|
14
|
+
import { _require } from './mdPlugins'
|
|
14
15
|
import { joinPath } from './index'
|
|
15
16
|
|
|
16
17
|
export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
@@ -32,7 +33,7 @@ export function getVitePlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
32
33
|
|
|
33
34
|
// 内置支持Mermaid
|
|
34
35
|
if (cfg?.mermaid !== false) {
|
|
35
|
-
const { MermaidPlugin } =
|
|
36
|
+
const { MermaidPlugin } = _require('vitepress-plugin-mermaid')
|
|
36
37
|
plugins.push(MermaidPlugin(cfg?.mermaid === true ? {} : (cfg?.mermaid ?? {})))
|
|
37
38
|
}
|
|
38
39
|
|