@sugarat/theme 0.2.17 → 0.2.19
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 +11 -0
- package/node.js +11 -11
- package/package.json +3 -1
- package/src/components/BlogApp.vue +2 -2
- package/src/components/BlogBackToTop.vue +2 -2
- package/src/components/BlogComment.vue +3 -3
- package/src/components/BlogFriendLink.vue +44 -37
- package/src/composables/config/index.ts +11 -1
- package/src/index.ts +5 -1
- package/src/utils/node/mdPlugins.ts +10 -12
package/node.d.ts
CHANGED
|
@@ -365,8 +365,19 @@ declare namespace Theme {
|
|
|
365
365
|
/**
|
|
366
366
|
* 配置内置的 markdown-it-task-checkbox 插件,设置 false 则关闭
|
|
367
367
|
* 详见 https://github.com/linsir/markdown-it-task-checkbox
|
|
368
|
+
* @default true
|
|
368
369
|
*/
|
|
369
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
|
+
*/
|
|
370
381
|
backToTop?: boolean | BackToTop;
|
|
371
382
|
}
|
|
372
383
|
interface BackToTop {
|
package/node.js
CHANGED
|
@@ -203,6 +203,9 @@ var tabsPlugin = (md) => {
|
|
|
203
203
|
};
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
+
// src/utils/node/mdPlugins.ts
|
|
207
|
+
var import_vitepress_markdown_timeline = __toESM(require("vitepress-markdown-timeline"));
|
|
208
|
+
|
|
206
209
|
// src/utils/node/index.ts
|
|
207
210
|
var import_node_child_process = require("child_process");
|
|
208
211
|
var import_node_path = __toESM(require("path"));
|
|
@@ -324,18 +327,15 @@ function getMarkdownPlugins(cfg) {
|
|
|
324
327
|
if (cfg?.tabs !== false) {
|
|
325
328
|
markdownPlugin.push(tabsPlugin);
|
|
326
329
|
}
|
|
327
|
-
if (cfg) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const { MermaidMarkdown } = _require("vitepress-plugin-mermaid");
|
|
331
|
-
markdownPlugin.push(MermaidMarkdown);
|
|
332
|
-
}
|
|
330
|
+
if (cfg?.mermaid !== false) {
|
|
331
|
+
const { MermaidMarkdown } = _require("vitepress-plugin-mermaid");
|
|
332
|
+
markdownPlugin.push(MermaidMarkdown);
|
|
333
333
|
}
|
|
334
|
-
if (cfg) {
|
|
335
|
-
cfg
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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);
|
|
339
339
|
}
|
|
340
340
|
return markdownPlugin;
|
|
341
341
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.19",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
"gray-matter": "^4.0.3",
|
|
43
43
|
"markdown-it-task-checkbox": "^1.0.6",
|
|
44
44
|
"mermaid": "^10.2.4",
|
|
45
|
+
"swiper": "^11.0.5",
|
|
46
|
+
"vitepress-markdown-timeline": "^1.2.1",
|
|
45
47
|
"vitepress-plugin-mermaid": "2.0.13",
|
|
46
48
|
"vitepress-plugin-pagefind": "0.2.10",
|
|
47
49
|
"vitepress-plugin-rss": "0.2.1",
|
|
@@ -28,8 +28,8 @@ const iconSVGStr = computed(() => typeof backToTopConfig === 'boolean' ? '' : ba
|
|
|
28
28
|
|
|
29
29
|
<template>
|
|
30
30
|
<div v-if="open" v-show="show" class="back-to-top">
|
|
31
|
-
<span class="icon-wrapper">
|
|
32
|
-
<ElIcon
|
|
31
|
+
<span class="icon-wrapper" @click="handleBackRoTop">
|
|
32
|
+
<ElIcon :size="20">
|
|
33
33
|
<i v-if="iconSVGStr" v-outer-html="iconSVGStr" />
|
|
34
34
|
<svg v-else width="512" height="512" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
35
35
|
<path
|
|
@@ -94,15 +94,15 @@ const labelText = computed(() => {
|
|
|
94
94
|
|
|
95
95
|
<div v-show="!commentIsVisible" class="comment-btn-wrapper">
|
|
96
96
|
<span v-if="!mobileMinify && labelText" class="icon-wrapper-text" @click="handleScrollToComment">
|
|
97
|
-
<ElIcon>
|
|
97
|
+
<ElIcon :size="20">
|
|
98
98
|
<CommentIcon />
|
|
99
99
|
</ElIcon>
|
|
100
100
|
<span class="text">
|
|
101
101
|
{{ labelText }}
|
|
102
102
|
</span>
|
|
103
103
|
</span>
|
|
104
|
-
<span v-else class="icon-wrapper">
|
|
105
|
-
<ElIcon
|
|
104
|
+
<span v-else class="icon-wrapper" @click="handleScrollToComment">
|
|
105
|
+
<ElIcon :size="20">
|
|
106
106
|
<CommentIcon />
|
|
107
107
|
</ElIcon>
|
|
108
108
|
</span>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { ElAvatar } from 'element-plus'
|
|
3
|
-
import { useDark } from '@vueuse/core'
|
|
4
|
-
import { computed } from 'vue'
|
|
3
|
+
import { useDark, useIntervalFn } from '@vueuse/core'
|
|
4
|
+
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
5
|
+
import Swiper from 'swiper'
|
|
5
6
|
import { useBlogConfig } from '../composables/config/blog'
|
|
6
7
|
import { getImageUrl, shuffleArray } from '../utils/client'
|
|
7
8
|
import type { Theme } from '../'
|
|
@@ -18,7 +19,6 @@ const friendConfig = computed<Theme.FriendConfig>(() => ({
|
|
|
18
19
|
...(Array.isArray(friend) ? { list: friend } : friend)
|
|
19
20
|
}))
|
|
20
21
|
|
|
21
|
-
// TODO: 待优化
|
|
22
22
|
const limit = computed(() => {
|
|
23
23
|
const { limit } = friendConfig.value
|
|
24
24
|
return (!limit || limit <= 0) ? 0 : limit || Number.MAX_SAFE_INTEGER
|
|
@@ -26,7 +26,7 @@ const limit = computed(() => {
|
|
|
26
26
|
|
|
27
27
|
const scrollSpeed = computed(() => {
|
|
28
28
|
const { scrollSpeed } = friendConfig.value
|
|
29
|
-
return
|
|
29
|
+
return scrollSpeed ?? 1500
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
const openScroll = computed(() => {
|
|
@@ -58,18 +58,37 @@ const friendList = computed(() => {
|
|
|
58
58
|
alt
|
|
59
59
|
}
|
|
60
60
|
})
|
|
61
|
-
return
|
|
61
|
+
return list
|
|
62
62
|
})
|
|
63
63
|
|
|
64
|
-
const cardHeight =
|
|
64
|
+
const cardHeight = 76
|
|
65
65
|
const scrollWrapperHeight = computed(() => {
|
|
66
66
|
return openScroll.value ? limit.value * cardHeight : 0
|
|
67
67
|
})
|
|
68
68
|
const containerHeight = computed(() => {
|
|
69
69
|
return scrollWrapperHeight.value ? `${scrollWrapperHeight.value}px` : 'auto'
|
|
70
70
|
})
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
|
|
72
|
+
const swiper = ref<Swiper>()
|
|
73
|
+
const { resume, pause } = useIntervalFn(() => {
|
|
74
|
+
swiper.value?.slideNext()
|
|
75
|
+
}, scrollSpeed.value)
|
|
76
|
+
|
|
77
|
+
onMounted(() => {
|
|
78
|
+
pause()
|
|
79
|
+
if (openScroll.value) {
|
|
80
|
+
// eslint-disable-next-line no-new
|
|
81
|
+
swiper.value = new Swiper('.scroll-wrapper', {
|
|
82
|
+
direction: 'vertical',
|
|
83
|
+
slidesPerView: limit.value,
|
|
84
|
+
loop: true,
|
|
85
|
+
})
|
|
86
|
+
resume()
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
onUnmounted(() => {
|
|
91
|
+
pause()
|
|
73
92
|
})
|
|
74
93
|
</script>
|
|
75
94
|
|
|
@@ -102,17 +121,11 @@ const scrollTop = computed(() => {
|
|
|
102
121
|
height: containerHeight,
|
|
103
122
|
}"
|
|
104
123
|
>
|
|
105
|
-
<ol
|
|
106
|
-
|
|
107
|
-
animationPlayState: openScroll ? 'running' : 'paused',
|
|
108
|
-
animationDuration: `${scrollSpeed / 1000}s`,
|
|
109
|
-
}
|
|
110
|
-
"
|
|
111
|
-
>
|
|
112
|
-
<li v-for="(v, idx) in friendList" :key="idx">
|
|
124
|
+
<ol class="friend-list swiper-wrapper">
|
|
125
|
+
<li v-for=" (v, idx) in friendList" :key="idx" class="swiper-slide">
|
|
113
126
|
<a :href="v.url" target="_blank">
|
|
114
127
|
<ElAvatar :size="50" :src="v.avatar" :alt="v.alt" />
|
|
115
|
-
<div>
|
|
128
|
+
<div class="info-wrapper">
|
|
116
129
|
<span class="nickname">{{ v.nickname }}</span>
|
|
117
130
|
<p class="des">{{ v.des }}</p>
|
|
118
131
|
</div>
|
|
@@ -159,15 +172,6 @@ const scrollTop = computed(() => {
|
|
|
159
172
|
flex-direction: column;
|
|
160
173
|
}
|
|
161
174
|
|
|
162
|
-
@keyframes scrollList {
|
|
163
|
-
0% {
|
|
164
|
-
top: 0;
|
|
165
|
-
}
|
|
166
|
-
100% {
|
|
167
|
-
top: v-bind(scrollTop);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
175
|
.scroll-wrapper {
|
|
172
176
|
overflow: hidden;
|
|
173
177
|
position: relative;
|
|
@@ -178,35 +182,35 @@ const scrollTop = computed(() => {
|
|
|
178
182
|
flex-direction: column;
|
|
179
183
|
list-style: none;
|
|
180
184
|
margin: 0;
|
|
181
|
-
padding:
|
|
185
|
+
padding: 10px 10px 0 0px;
|
|
182
186
|
width: 100%;
|
|
183
187
|
|
|
184
188
|
position: relative;
|
|
185
189
|
width: 100%;
|
|
186
|
-
animation-name: scrollList;
|
|
187
|
-
animation-timing-function:linear;
|
|
188
|
-
animation-iteration-count:infinite;
|
|
189
|
-
|
|
190
|
-
&:hover {
|
|
191
|
-
animation-play-state: paused !important;
|
|
192
|
-
}
|
|
193
190
|
|
|
194
191
|
li {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
box-sizing: border-box;
|
|
193
|
+
padding: 0 5px;
|
|
194
|
+
height: 76px;
|
|
198
195
|
.el-avatar {
|
|
199
196
|
min-width: 50px;
|
|
200
197
|
}
|
|
201
198
|
|
|
202
199
|
a {
|
|
203
200
|
display: flex;
|
|
201
|
+
align-items: center;
|
|
204
202
|
}
|
|
205
203
|
|
|
206
204
|
div {
|
|
207
205
|
padding-left: 10px;
|
|
208
206
|
}
|
|
209
207
|
|
|
208
|
+
.info-wrapper {
|
|
209
|
+
display: flex;
|
|
210
|
+
flex-direction: column;
|
|
211
|
+
overflow: hidden;
|
|
212
|
+
}
|
|
213
|
+
|
|
210
214
|
.nickname {
|
|
211
215
|
font-size: 16px;
|
|
212
216
|
font-weight: 450;
|
|
@@ -215,6 +219,9 @@ const scrollTop = computed(() => {
|
|
|
215
219
|
.des {
|
|
216
220
|
color: var(--vp-c-text-2);
|
|
217
221
|
font-size: 14px;
|
|
222
|
+
overflow: hidden;
|
|
223
|
+
white-space: nowrap;
|
|
224
|
+
text-overflow: ellipsis;
|
|
218
225
|
}
|
|
219
226
|
}
|
|
220
227
|
}
|
|
@@ -397,9 +397,19 @@ export namespace Theme {
|
|
|
397
397
|
/**
|
|
398
398
|
* 配置内置的 markdown-it-task-checkbox 插件,设置 false 则关闭
|
|
399
399
|
* 详见 https://github.com/linsir/markdown-it-task-checkbox
|
|
400
|
+
* @default true
|
|
400
401
|
*/
|
|
401
402
|
taskCheckbox?: TaskCheckbox | boolean
|
|
402
|
-
|
|
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
|
+
*/
|
|
403
413
|
backToTop?: boolean | BackToTop
|
|
404
414
|
}
|
|
405
415
|
|
package/src/index.ts
CHANGED
|
@@ -5,9 +5,13 @@ 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
|
+
// 图表渲染组件
|
|
11
15
|
import Mermaid from 'vitepress-plugin-mermaid/Mermaid.vue'
|
|
12
16
|
import BlogApp from './components/BlogApp.vue'
|
|
13
17
|
import { withConfigProvider } from './composables/config/blog'
|
|
@@ -27,7 +31,7 @@ export const BlogTheme: Theme = {
|
|
|
27
31
|
DefaultTheme.enhanceApp(ctx)
|
|
28
32
|
ctx.app.component('TimelinePage', TimelinePage)
|
|
29
33
|
ctx.app.component('UserWorksPage', UserWorksPage)
|
|
30
|
-
ctx.app.component('Mermaid', Mermaid)
|
|
34
|
+
ctx.app.component('Mermaid', Mermaid as any)
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'module'
|
|
3
3
|
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
|
4
4
|
import type { UserConfig } from 'vitepress'
|
|
5
|
+
import timeline from 'vitepress-markdown-timeline'
|
|
5
6
|
import type { Theme } from '../../composables/config/index'
|
|
6
7
|
import { aliasObjectToArray } from './index'
|
|
7
8
|
|
|
@@ -17,25 +18,22 @@ export function getMarkdownPlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
// 添加mermaid markdown 插件
|
|
20
|
-
if (cfg) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const { MermaidMarkdown } = _require('vitepress-plugin-mermaid')
|
|
24
|
-
markdownPlugin.push(MermaidMarkdown)
|
|
25
|
-
}
|
|
21
|
+
if (cfg?.mermaid !== false) {
|
|
22
|
+
const { MermaidMarkdown } = _require('vitepress-plugin-mermaid')
|
|
23
|
+
markdownPlugin.push(MermaidMarkdown)
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
if (cfg) {
|
|
29
|
-
cfg
|
|
30
|
-
if (cfg.taskCheckbox !== false) {
|
|
31
|
-
markdownPlugin.push(taskCheckboxPlugin(cfg.taskCheckbox))
|
|
32
|
-
}
|
|
26
|
+
if (cfg.taskCheckbox !== false) {
|
|
27
|
+
markdownPlugin.push(taskCheckboxPlugin(typeof cfg?.taskCheckbox === 'boolean' ? {} : cfg?.taskCheckbox))
|
|
33
28
|
}
|
|
34
29
|
|
|
30
|
+
if (cfg?.timeline !== false) {
|
|
31
|
+
markdownPlugin.push(timeline)
|
|
32
|
+
}
|
|
35
33
|
return markdownPlugin
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
export function taskCheckboxPlugin(ops
|
|
36
|
+
export function taskCheckboxPlugin(ops?: Theme.TaskCheckbox) {
|
|
39
37
|
return (md: any) => {
|
|
40
38
|
md.use(_require('markdown-it-task-checkbox'), ops)
|
|
41
39
|
}
|