@sugarat/theme 0.2.3 → 0.2.5
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/README.md +3 -0
- package/node.d.ts +22 -5
- package/node.js +1 -1
- package/package.json +4 -3
- package/src/components/BlogApp.vue +2 -0
- package/src/components/BlogComment.vue +16 -28
- package/src/components/BlogFooter.vue +77 -61
- package/src/components/BlogHomeBanner.vue +2 -0
- package/src/components/BlogHomeHeaderAvatar.vue +50 -0
- package/src/components/BlogHomeInfo.vue +0 -4
- package/src/components/BlogHomeOverview.vue +30 -15
- package/src/components/BlogRecommendArticle.vue +18 -1
- package/src/composables/config/blog.ts +1 -1
- package/src/composables/config/index.ts +22 -5
- package/src/styles/index.scss +1 -1
package/README.md
CHANGED
package/node.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DefaultTheme, UserConfig } from 'vitepress';
|
|
2
2
|
import { ElButton } from 'element-plus';
|
|
3
3
|
import { RSSOptions } from 'vitepress-plugin-rss';
|
|
4
|
+
import { Repo, Mapping } from '@giscus/vue';
|
|
4
5
|
export { tabsMarkdownPlugin } from 'vitepress-plugin-tabs';
|
|
5
6
|
|
|
6
7
|
type RSSPluginOptions = RSSOptions;
|
|
@@ -82,14 +83,14 @@ declare namespace Theme {
|
|
|
82
83
|
type: string;
|
|
83
84
|
}
|
|
84
85
|
interface GiscusConfig {
|
|
85
|
-
repo:
|
|
86
|
+
repo: Repo;
|
|
86
87
|
repoId: string;
|
|
87
88
|
category: string;
|
|
88
89
|
categoryId: string;
|
|
89
|
-
mapping?:
|
|
90
|
+
mapping?: Mapping;
|
|
90
91
|
inputPosition?: 'top' | 'bottom';
|
|
91
92
|
lang?: string;
|
|
92
|
-
loading?: 'lazy' | '
|
|
93
|
+
loading?: 'lazy' | 'eager';
|
|
93
94
|
}
|
|
94
95
|
interface HotArticle {
|
|
95
96
|
title?: string;
|
|
@@ -106,7 +107,19 @@ declare namespace Theme {
|
|
|
106
107
|
* @default true
|
|
107
108
|
*/
|
|
108
109
|
showSelf?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* 自定义文章过滤
|
|
112
|
+
*/
|
|
109
113
|
filter?: (page: Theme.PageData) => boolean;
|
|
114
|
+
/**
|
|
115
|
+
* 自定义排序
|
|
116
|
+
* @default 'date'
|
|
117
|
+
*/
|
|
118
|
+
sort?: 'date' | 'filename' | ((a: Theme.PageData, b: Theme.PageData) => number);
|
|
119
|
+
/**
|
|
120
|
+
* 当没有推荐文章时的提示,设置为 false 则不展示
|
|
121
|
+
* @default '暂无相关文章'
|
|
122
|
+
*/
|
|
110
123
|
empty?: string | boolean;
|
|
111
124
|
/**
|
|
112
125
|
* 设置推荐文章的展示风格
|
|
@@ -122,6 +135,10 @@ declare namespace Theme {
|
|
|
122
135
|
pageSize?: number;
|
|
123
136
|
author?: string | boolean;
|
|
124
137
|
logo?: string | boolean;
|
|
138
|
+
/**
|
|
139
|
+
* @default 'card'
|
|
140
|
+
*/
|
|
141
|
+
avatarMode?: 'card' | 'split';
|
|
125
142
|
}
|
|
126
143
|
interface ArticleConfig {
|
|
127
144
|
readingTime?: boolean;
|
|
@@ -272,14 +289,14 @@ declare namespace Theme {
|
|
|
272
289
|
/**
|
|
273
290
|
* 首页页脚
|
|
274
291
|
*/
|
|
275
|
-
footer?: Footer;
|
|
292
|
+
footer?: Footer | Footer[];
|
|
276
293
|
}
|
|
277
294
|
type RSSOptions = RSSPluginOptions;
|
|
278
295
|
interface Footer {
|
|
279
296
|
/**
|
|
280
297
|
* 自定义补充信息
|
|
281
298
|
*/
|
|
282
|
-
message?: string;
|
|
299
|
+
message?: string | string[];
|
|
283
300
|
/**
|
|
284
301
|
* 是否展示主题版本信息
|
|
285
302
|
*/
|
package/node.js
CHANGED
|
@@ -36,7 +36,7 @@ __export(node_exports, {
|
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(node_exports);
|
|
38
38
|
|
|
39
|
-
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.
|
|
39
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.20_vue@3.3.4/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
40
40
|
var tabsMarker = "=tabs";
|
|
41
41
|
var tabsMarkerLen = tabsMarker.length;
|
|
42
42
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"types"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@giscus/vue": "^2.3.0",
|
|
36
37
|
"@mdit-vue/shared": "^0.12.0",
|
|
37
38
|
"@mermaid-js/mermaid-mindmap": "^9.3.0",
|
|
38
39
|
"@vue/shared": "^3.2.45",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"fast-glob": "^3.2.12",
|
|
41
42
|
"gray-matter": "^4.0.3",
|
|
42
43
|
"mermaid": "^10.2.4",
|
|
43
|
-
"vitepress-plugin-mermaid": "
|
|
44
|
+
"vitepress-plugin-mermaid": "2.0.13",
|
|
44
45
|
"vitepress-plugin-pagefind": "0.2.10",
|
|
45
46
|
"vitepress-plugin-rss": "0.1.3",
|
|
46
47
|
"vitepress-plugin-tabs": "0.2.0"
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
"pagefind": "1.0.3",
|
|
52
53
|
"sass": "^1.56.1",
|
|
53
54
|
"typescript": "^4.8.2",
|
|
54
|
-
"vitepress": "1.0.0-rc.
|
|
55
|
+
"vitepress": "1.0.0-rc.20",
|
|
55
56
|
"vue": "^3.3.4"
|
|
56
57
|
},
|
|
57
58
|
"scripts": {
|
|
@@ -15,6 +15,7 @@ import BlogArticleAnalyze from './BlogArticleAnalyze.vue'
|
|
|
15
15
|
import BlogAlert from './BlogAlert.vue'
|
|
16
16
|
import BlogPopover from './BlogPopover.vue'
|
|
17
17
|
import BlogFooter from './BlogFooter.vue'
|
|
18
|
+
import BlogHomeHeaderAvatar from './BlogHomeHeaderAvatar.vue'
|
|
18
19
|
|
|
19
20
|
const { frontmatter } = useData()
|
|
20
21
|
const layout = computed(() => frontmatter.value.layout)
|
|
@@ -49,6 +50,7 @@ const { Layout } = Theme
|
|
|
49
50
|
<template v-if="isBlogTheme" #home-hero-before>
|
|
50
51
|
<slot name="home-hero-before" />
|
|
51
52
|
<div class="home">
|
|
53
|
+
<BlogHomeHeaderAvatar />
|
|
52
54
|
<div class="header-banner">
|
|
53
55
|
<BlogHomeBanner />
|
|
54
56
|
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useElementVisibility } from '@vueuse/core'
|
|
3
3
|
import { useData, useRoute } from 'vitepress'
|
|
4
|
-
import { computed,
|
|
4
|
+
import { computed, ref, watch } from 'vue'
|
|
5
5
|
import { ElAffix, ElButton } from 'element-plus'
|
|
6
6
|
import { Comment } from '@element-plus/icons-vue'
|
|
7
|
+
import Giscus from '@giscus/vue'
|
|
7
8
|
import { useGiscusConfig } from '../composables/config/blog'
|
|
8
9
|
import type { Theme } from '../composables/config/index'
|
|
9
10
|
|
|
@@ -19,9 +20,9 @@ function handleScrollToComment() {
|
|
|
19
20
|
}
|
|
20
21
|
const giscusConfig = useGiscusConfig()
|
|
21
22
|
|
|
22
|
-
const commentConfig = computed<
|
|
23
|
+
const commentConfig = computed<Theme.GiscusConfig>(() => {
|
|
23
24
|
if (!giscusConfig) {
|
|
24
|
-
return {}
|
|
25
|
+
return {} as any
|
|
25
26
|
}
|
|
26
27
|
return giscusConfig
|
|
27
28
|
})
|
|
@@ -57,14 +58,6 @@ watch(
|
|
|
57
58
|
immediate: true
|
|
58
59
|
}
|
|
59
60
|
)
|
|
60
|
-
|
|
61
|
-
// TODO:可以优化,不需要重载
|
|
62
|
-
watch(isDark, () => {
|
|
63
|
-
showComment.value = false
|
|
64
|
-
nextTick(() => {
|
|
65
|
-
showComment.value = true
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
61
|
</script>
|
|
69
62
|
|
|
70
63
|
<template>
|
|
@@ -91,24 +84,19 @@ watch(isDark, () => {
|
|
|
91
84
|
评论
|
|
92
85
|
</ElButton>
|
|
93
86
|
</ElAffix>
|
|
94
|
-
|
|
95
|
-
<component
|
|
96
|
-
is="script"
|
|
87
|
+
<Giscus
|
|
97
88
|
v-if="showComment"
|
|
98
|
-
|
|
99
|
-
:
|
|
100
|
-
:
|
|
101
|
-
:
|
|
102
|
-
:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
:
|
|
107
|
-
:
|
|
108
|
-
:
|
|
109
|
-
crossorigin="anonymous"
|
|
110
|
-
:data-loading="commentConfig.loading || 'eager'"
|
|
111
|
-
async
|
|
89
|
+
:repo="commentConfig.repo"
|
|
90
|
+
:repo-id="commentConfig.repoId"
|
|
91
|
+
:category="commentConfig.category"
|
|
92
|
+
:category-id="commentConfig.categoryId"
|
|
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'"
|
|
112
100
|
/>
|
|
113
101
|
</div>
|
|
114
102
|
</template>
|
|
@@ -1,74 +1,90 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { computed } from 'vue'
|
|
3
3
|
import { useHomeFooterConfig } from '../composables/config/blog'
|
|
4
4
|
import packageJSON from '../../package.json'
|
|
5
5
|
import { copyrightSVG, icpSVG, themeSVG } from '../constants/svg'
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}[]>([])
|
|
13
|
-
onMounted(() => {
|
|
14
|
-
if (!footer) {
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
const { icpRecord, securityRecord, copyright, version } = footer
|
|
18
|
-
// version
|
|
19
|
-
if (version !== false) {
|
|
20
|
-
data.value.push({
|
|
21
|
-
name: `@sugarat/theme@${packageJSON.version}`,
|
|
22
|
-
link: 'https://theme.sugarat.top/',
|
|
23
|
-
icon: themeSVG
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
// copyright
|
|
27
|
-
if (typeof copyright === 'string') {
|
|
28
|
-
data.value.push({
|
|
29
|
-
name: copyright,
|
|
30
|
-
icon: copyrightSVG
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
if (copyright instanceof Object) {
|
|
34
|
-
data.value.push({
|
|
35
|
-
icon: copyrightSVG,
|
|
36
|
-
name: copyright.message,
|
|
37
|
-
...copyright
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
// 备案信息
|
|
41
|
-
if (icpRecord) {
|
|
42
|
-
data.value.push({
|
|
43
|
-
icon: icpSVG,
|
|
44
|
-
...icpRecord
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
// 网备信息
|
|
48
|
-
if (securityRecord) {
|
|
49
|
-
data.value.push({
|
|
50
|
-
icon: 'security',
|
|
51
|
-
...securityRecord
|
|
52
|
-
})
|
|
7
|
+
const footerData = useHomeFooterConfig()
|
|
8
|
+
|
|
9
|
+
const renderData = computed(() => {
|
|
10
|
+
if (!footerData) {
|
|
11
|
+
return []
|
|
53
12
|
}
|
|
13
|
+
const flatData = [footerData].flat()
|
|
14
|
+
return flatData.flat().map((footer, idx) => {
|
|
15
|
+
const { icpRecord, securityRecord, copyright, version, message } = footer
|
|
16
|
+
const data: {
|
|
17
|
+
name: string
|
|
18
|
+
link?: string
|
|
19
|
+
icon?: string | boolean
|
|
20
|
+
}[] = []
|
|
21
|
+
// message
|
|
22
|
+
const messageData: string[] = [message || []].flat()
|
|
23
|
+
|
|
24
|
+
// version
|
|
25
|
+
const isLast = idx === flatData.length - 1
|
|
26
|
+
if ((version !== false && isLast) || version === true) {
|
|
27
|
+
data.push({
|
|
28
|
+
name: `@sugarat/theme@${packageJSON.version}`,
|
|
29
|
+
link: 'https://theme.sugarat.top/',
|
|
30
|
+
icon: themeSVG
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
// copyright
|
|
34
|
+
if (typeof copyright === 'string') {
|
|
35
|
+
data.push({
|
|
36
|
+
name: copyright,
|
|
37
|
+
icon: copyrightSVG
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
if (copyright instanceof Object) {
|
|
41
|
+
data.push({
|
|
42
|
+
icon: copyrightSVG,
|
|
43
|
+
name: copyright.message,
|
|
44
|
+
...copyright
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
// 备案信息
|
|
48
|
+
if (icpRecord) {
|
|
49
|
+
data.push({
|
|
50
|
+
icon: icpSVG,
|
|
51
|
+
...icpRecord
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
// 网备信息
|
|
55
|
+
if (securityRecord) {
|
|
56
|
+
data.push({
|
|
57
|
+
icon: 'security',
|
|
58
|
+
...securityRecord
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
data,
|
|
63
|
+
messageData
|
|
64
|
+
}
|
|
65
|
+
})
|
|
54
66
|
})
|
|
55
67
|
</script>
|
|
56
68
|
|
|
57
69
|
<template>
|
|
58
|
-
<footer v-if="
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
<footer v-if="renderData.length" class="blog-footer">
|
|
71
|
+
<!-- eslint-disable vue/require-v-for-key -->
|
|
72
|
+
<!-- see https://cn.vuejs.org/guide/essentials/list.html#v-for-on-template -->
|
|
73
|
+
<template v-for="({ data, messageData }) in renderData">
|
|
74
|
+
<p v-for="message in messageData" v-html="message" />
|
|
75
|
+
<p class="footer-item-list">
|
|
76
|
+
<span v-for="item in data" class="footer-item">
|
|
77
|
+
<i v-if="item.icon === 'security'">
|
|
78
|
+
<img src="./../styles/gongan.png" alt="公网安备">
|
|
79
|
+
</i>
|
|
80
|
+
<i v-else-if="item.icon" v-html="item.icon" />
|
|
81
|
+
<a v-if="item.link" :href="item.link" target="_blank" rel="noopener noreferrer">
|
|
82
|
+
{{ item.name }}
|
|
83
|
+
</a>
|
|
84
|
+
<span v-else>{{ item.name }}</span>
|
|
85
|
+
</span>
|
|
86
|
+
</p>
|
|
87
|
+
</template>
|
|
72
88
|
</footer>
|
|
73
89
|
</template>
|
|
74
90
|
|
|
@@ -113,6 +113,7 @@ h1 {
|
|
|
113
113
|
display: none;
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
+
|
|
116
117
|
@keyframes fade-in {
|
|
117
118
|
0% {
|
|
118
119
|
opacity: 0;
|
|
@@ -127,6 +128,7 @@ h1 {
|
|
|
127
128
|
margin: 16px 0;
|
|
128
129
|
height: 24px;
|
|
129
130
|
width: auto;
|
|
131
|
+
|
|
130
132
|
h2 {
|
|
131
133
|
animation: fade-in 0.5s ease-in-out;
|
|
132
134
|
cursor: pointer;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useData } from 'vitepress'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { useWindowSize } from '@vueuse/core'
|
|
5
|
+
import { useBlogConfig } from '../composables/config/blog'
|
|
6
|
+
|
|
7
|
+
const { width } = useWindowSize()
|
|
8
|
+
const inMiniScreen = computed(() => width.value <= 767)
|
|
9
|
+
|
|
10
|
+
const { home } = useBlogConfig()
|
|
11
|
+
const { frontmatter, site } = useData()
|
|
12
|
+
const logo = computed(() =>
|
|
13
|
+
frontmatter.value.logo
|
|
14
|
+
?? frontmatter.value?.blog?.logo
|
|
15
|
+
?? home?.logo
|
|
16
|
+
?? site.value.themeConfig.logo
|
|
17
|
+
)
|
|
18
|
+
const alwaysHide = computed(() => frontmatter.value.blog?.minScreenAvatar === false)
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<div v-show="inMiniScreen && !alwaysHide" class="blog-home-header-avatar">
|
|
23
|
+
<img :src="logo" alt="avatar">
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<style lang="scss" scoped>
|
|
28
|
+
.blog-home-header-avatar {
|
|
29
|
+
padding-top: 40px;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
|
|
33
|
+
img {
|
|
34
|
+
display: block;
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
width: 130px;
|
|
37
|
+
height: 130px;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
background-color: transparent;
|
|
40
|
+
border: 5px solid rgba(var(--bg-gradient-home));
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
img:hover {
|
|
45
|
+
transform: rotate(666turn);
|
|
46
|
+
transition-duration: 59s;
|
|
47
|
+
transition-timing-function: cubic-bezier(.34, 0, .84, 1)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -3,14 +3,10 @@ import BlogHomeOverview from './BlogHomeOverview.vue'
|
|
|
3
3
|
import BlogHotArticle from './BlogHotArticle.vue'
|
|
4
4
|
import BlogHomeTags from './BlogHomeTags.vue'
|
|
5
5
|
import BlogFriendLink from './BlogFriendLink.vue'
|
|
6
|
-
import BlogAuthor from './BlogAuthor.vue'
|
|
7
6
|
</script>
|
|
8
7
|
|
|
9
8
|
<template>
|
|
10
9
|
<div class="blog-info" data-pagefind-ignore="all">
|
|
11
|
-
<!-- 头像信息 -->
|
|
12
|
-
<BlogAuthor />
|
|
13
|
-
|
|
14
10
|
<!-- 统计数据,日后支持,点击筛选出左侧的数据 -->
|
|
15
11
|
<BlogHomeOverview />
|
|
16
12
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
+
import { useData } from 'vitepress'
|
|
3
4
|
import { isCurrentWeek } from '../utils/client'
|
|
4
|
-
import { useArticles } from '../composables/config/blog'
|
|
5
|
+
import { useArticles, useBlogConfig } from '../composables/config/blog'
|
|
6
|
+
import BlogAuthor from './BlogAuthor.vue'
|
|
7
|
+
|
|
8
|
+
const { home } = useBlogConfig()
|
|
9
|
+
const { frontmatter } = useData()
|
|
10
|
+
const avatarMode = computed(() => frontmatter.value?.blog?.avatarMode || home?.avatarMode || 'card')
|
|
11
|
+
|
|
12
|
+
const showCardAvatar = computed(() => avatarMode.value === 'card')
|
|
13
|
+
const showSplitCard = computed(() => avatarMode.value === 'split')
|
|
5
14
|
|
|
6
15
|
const docs = useArticles()
|
|
7
16
|
const notHiddenArticles = computed(() => {
|
|
@@ -25,20 +34,25 @@ const currentWeek = computed(() => {
|
|
|
25
34
|
</script>
|
|
26
35
|
|
|
27
36
|
<template>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
<!-- 头像信息 -->
|
|
38
|
+
<BlogAuthor v-if="showSplitCard" />
|
|
39
|
+
<div class="card">
|
|
40
|
+
<BlogAuthor v-if="showCardAvatar" />
|
|
41
|
+
<div class="overview-data">
|
|
42
|
+
<div class="overview-item">
|
|
43
|
+
<span class="count">{{ notHiddenArticles.length }}</span>
|
|
44
|
+
<span class="label">博客文章</span>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="split" />
|
|
47
|
+
<div class="overview-item">
|
|
48
|
+
<span class="count">+{{ currentMonth?.length }}</span>
|
|
49
|
+
<span class="label">本月更新</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="split" />
|
|
52
|
+
<div class="overview-item">
|
|
53
|
+
<span class="count">+{{ currentWeek?.length }}</span>
|
|
54
|
+
<span class="label">本周更新</span>
|
|
55
|
+
</div>
|
|
42
56
|
</div>
|
|
43
57
|
</div>
|
|
44
58
|
</template>
|
|
@@ -56,6 +70,7 @@ const currentWeek = computed(() => {
|
|
|
56
70
|
transition: all 0.3s;
|
|
57
71
|
background-color: rgba(var(--bg-gradient));
|
|
58
72
|
display: flex;
|
|
73
|
+
flex-direction: column;
|
|
59
74
|
|
|
60
75
|
&:hover {
|
|
61
76
|
box-shadow: var(--box-shadow-hover);
|
|
@@ -56,7 +56,24 @@ const recommendList = computed(() => {
|
|
|
56
56
|
topList.sort((a, b) => Number(a.meta.recommend) - Number(b.meta.recommend))
|
|
57
57
|
|
|
58
58
|
const normalList = origin.filter(v => !v.meta?.recommend)
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
// 排序
|
|
61
|
+
const sortMode = recommend.value?.sort ?? 'date'
|
|
62
|
+
// 默认时间排序
|
|
63
|
+
let compareFn = (a: any, b: any) => +new Date(b.meta.date) - +new Date(a.meta.date)
|
|
64
|
+
// 文件名排序
|
|
65
|
+
if (sortMode === 'filename') {
|
|
66
|
+
compareFn = (a: any, b: any) => {
|
|
67
|
+
const aName = a.route.split('/').pop()
|
|
68
|
+
const bName = b.route.split('/').pop()
|
|
69
|
+
return aName.localeCompare(bName)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 自定义排序
|
|
73
|
+
if (typeof sortMode === 'function') {
|
|
74
|
+
compareFn = sortMode
|
|
75
|
+
}
|
|
76
|
+
normalList.sort(compareFn)
|
|
60
77
|
|
|
61
78
|
return topList.concat(normalList)
|
|
62
79
|
})
|
|
@@ -27,7 +27,7 @@ const currentPageNum: InjectionKey<Ref<number>> = Symbol('home-page-num')
|
|
|
27
27
|
|
|
28
28
|
const userWorks: InjectionKey<Ref<Theme.UserWorks>> = Symbol('user-works')
|
|
29
29
|
|
|
30
|
-
const homeFooter: InjectionKey<Theme.Footer | undefined> = Symbol('home-footer')
|
|
30
|
+
const homeFooter: InjectionKey<Theme.Footer | Theme.Footer[] | undefined> = Symbol('home-footer')
|
|
31
31
|
|
|
32
32
|
export function withConfigProvider(App: Component) {
|
|
33
33
|
return defineComponent({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { ElButton } from 'element-plus'
|
|
3
3
|
import type { DefaultTheme } from 'vitepress'
|
|
4
4
|
import type { RSSOptions } from 'vitepress-plugin-rss'
|
|
5
|
+
import type { Mapping, Repo } from '@giscus/vue'
|
|
5
6
|
|
|
6
7
|
type RSSPluginOptions = RSSOptions
|
|
7
8
|
|
|
@@ -89,14 +90,14 @@ export namespace Theme {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
export interface GiscusConfig {
|
|
92
|
-
repo:
|
|
93
|
+
repo: Repo
|
|
93
94
|
repoId: string
|
|
94
95
|
category: string
|
|
95
96
|
categoryId: string
|
|
96
|
-
mapping?:
|
|
97
|
+
mapping?: Mapping
|
|
97
98
|
inputPosition?: 'top' | 'bottom'
|
|
98
99
|
lang?: string
|
|
99
|
-
loading?: 'lazy' | '
|
|
100
|
+
loading?: 'lazy' | 'eager'
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
export interface HotArticle {
|
|
@@ -114,7 +115,19 @@ export namespace Theme {
|
|
|
114
115
|
* @default true
|
|
115
116
|
*/
|
|
116
117
|
showSelf?: boolean
|
|
118
|
+
/**
|
|
119
|
+
* 自定义文章过滤
|
|
120
|
+
*/
|
|
117
121
|
filter?: (page: Theme.PageData) => boolean
|
|
122
|
+
/**
|
|
123
|
+
* 自定义排序
|
|
124
|
+
* @default 'date'
|
|
125
|
+
*/
|
|
126
|
+
sort?: 'date' | 'filename' | ((a: Theme.PageData, b: Theme.PageData) => number)
|
|
127
|
+
/**
|
|
128
|
+
* 当没有推荐文章时的提示,设置为 false 则不展示
|
|
129
|
+
* @default '暂无相关文章'
|
|
130
|
+
*/
|
|
118
131
|
empty?: string | boolean
|
|
119
132
|
/**
|
|
120
133
|
* 设置推荐文章的展示风格
|
|
@@ -131,6 +144,10 @@ export namespace Theme {
|
|
|
131
144
|
pageSize?: number
|
|
132
145
|
author?: string | boolean
|
|
133
146
|
logo?: string | boolean
|
|
147
|
+
/**
|
|
148
|
+
* @default 'card'
|
|
149
|
+
*/
|
|
150
|
+
avatarMode?: 'card' | 'split'
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
export interface ArticleConfig {
|
|
@@ -303,7 +320,7 @@ export namespace Theme {
|
|
|
303
320
|
/**
|
|
304
321
|
* 首页页脚
|
|
305
322
|
*/
|
|
306
|
-
footer?: Footer
|
|
323
|
+
footer?: Footer | Footer[]
|
|
307
324
|
}
|
|
308
325
|
|
|
309
326
|
export type RSSOptions = RSSPluginOptions
|
|
@@ -312,7 +329,7 @@ export namespace Theme {
|
|
|
312
329
|
/**
|
|
313
330
|
* 自定义补充信息
|
|
314
331
|
*/
|
|
315
|
-
message?: string
|
|
332
|
+
message?: string | string[]
|
|
316
333
|
/**
|
|
317
334
|
* 是否展示主题版本信息
|
|
318
335
|
*/
|