@sugarat/theme 0.2.30 → 0.3.0
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 +34 -3
- package/node.js +12 -1
- package/package.json +3 -2
- package/src/components/BlogApp.vue +11 -3
- package/src/components/BlogButtonAfterArticle.vue +122 -0
- package/src/components/{BlogComment.vue → BlogCommentWrapper.vue} +14 -54
- package/src/components/BlogHomeTags.vue +1 -1
- package/src/components/BlogItem.vue +4 -2
- package/src/components/CommentArtalk.vue +74 -0
- package/src/components/CommentGiscus.vue +49 -0
- package/src/composables/config/blog.ts +0 -5
- package/src/composables/config/index.ts +35 -3
- package/src/constants/svg.ts +23 -0
- package/src/node.ts +3 -1
- package/src/utils/node/theme.ts +9 -1
- package/types/vue-shim.d.ts +10 -0
package/node.d.ts
CHANGED
|
@@ -93,7 +93,8 @@ declare namespace Theme {
|
|
|
93
93
|
label: string;
|
|
94
94
|
type: string;
|
|
95
95
|
}
|
|
96
|
-
|
|
96
|
+
type CommentConfig = ((GiscusOption & CommentCommonConfig) | GiscusConfig | ArtalkConfig);
|
|
97
|
+
interface CommentCommonConfig {
|
|
97
98
|
/**
|
|
98
99
|
* @default '评论'
|
|
99
100
|
*/
|
|
@@ -109,7 +110,15 @@ declare namespace Theme {
|
|
|
109
110
|
*/
|
|
110
111
|
mobileMinify?: boolean;
|
|
111
112
|
}
|
|
112
|
-
interface GiscusConfig {
|
|
113
|
+
interface GiscusConfig extends CommentCommonConfig {
|
|
114
|
+
type: 'giscus';
|
|
115
|
+
options: GiscusOption;
|
|
116
|
+
}
|
|
117
|
+
interface ArtalkConfig extends CommentCommonConfig {
|
|
118
|
+
type: 'artalk';
|
|
119
|
+
options: ArtalkOption;
|
|
120
|
+
}
|
|
121
|
+
interface GiscusOption {
|
|
113
122
|
repo: Repo;
|
|
114
123
|
repoId: string;
|
|
115
124
|
category: string;
|
|
@@ -119,6 +128,10 @@ declare namespace Theme {
|
|
|
119
128
|
lang?: string;
|
|
120
129
|
loading?: 'lazy' | 'eager';
|
|
121
130
|
}
|
|
131
|
+
interface ArtalkOption {
|
|
132
|
+
site: string;
|
|
133
|
+
server: string;
|
|
134
|
+
}
|
|
122
135
|
interface HotArticle {
|
|
123
136
|
title?: string;
|
|
124
137
|
pageSize?: number;
|
|
@@ -319,7 +332,8 @@ declare namespace Theme {
|
|
|
319
332
|
search?: SearchConfig;
|
|
320
333
|
/**
|
|
321
334
|
* 配置评论
|
|
322
|
-
*
|
|
335
|
+
* giscus: https://giscus.app/zh-CN
|
|
336
|
+
* artalk: https://artalk.js.org/
|
|
323
337
|
*/
|
|
324
338
|
comment?: CommentConfig | false;
|
|
325
339
|
/**
|
|
@@ -391,6 +405,7 @@ declare namespace Theme {
|
|
|
391
405
|
*/
|
|
392
406
|
oml2d?: Options;
|
|
393
407
|
homeTags?: boolean;
|
|
408
|
+
buttonAfterArticle?: ButtonAfterArticleConfig | false;
|
|
394
409
|
}
|
|
395
410
|
interface BackToTop {
|
|
396
411
|
/**
|
|
@@ -470,6 +485,22 @@ declare namespace Theme {
|
|
|
470
485
|
*/
|
|
471
486
|
handleChangeSlogan?: (oldSlogan: string) => string | Promise<string>;
|
|
472
487
|
}
|
|
488
|
+
interface ButtonAfterArticleConfig {
|
|
489
|
+
openTitle?: string;
|
|
490
|
+
closeTitle?: string;
|
|
491
|
+
content?: string;
|
|
492
|
+
icon?: 'aliPay' | 'wechatPay' | string;
|
|
493
|
+
/**
|
|
494
|
+
* 按钮尺寸
|
|
495
|
+
* @default 'default'
|
|
496
|
+
*/
|
|
497
|
+
size?: 'small' | 'default' | 'large';
|
|
498
|
+
/**
|
|
499
|
+
* 默认展开
|
|
500
|
+
* @default false
|
|
501
|
+
*/
|
|
502
|
+
expand?: boolean;
|
|
503
|
+
}
|
|
473
504
|
}
|
|
474
505
|
|
|
475
506
|
/**
|
package/node.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(node_exports);
|
|
|
40
40
|
// src/utils/node/mdPlugins.ts
|
|
41
41
|
var import_module = require("module");
|
|
42
42
|
|
|
43
|
-
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.
|
|
43
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.2_vue@3.4.21/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
44
44
|
var tabsMarker = "=tabs";
|
|
45
45
|
var tabsMarkerLen = tabsMarker.length;
|
|
46
46
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
|
@@ -453,6 +453,16 @@ function getArticles(cfg) {
|
|
|
453
453
|
}).filter((v) => v.meta.layout !== "home");
|
|
454
454
|
return data;
|
|
455
455
|
}
|
|
456
|
+
function patchVPConfig(vpConfig, cfg) {
|
|
457
|
+
vpConfig.head = vpConfig.head || [];
|
|
458
|
+
if (cfg?.comment && "type" in cfg.comment && cfg?.comment?.type === "artalk") {
|
|
459
|
+
const server = cfg.comment?.options?.server;
|
|
460
|
+
if (server) {
|
|
461
|
+
vpConfig.head.push(["link", { href: `${server}/dist/Artalk.css`, rel: "stylesheet" }]);
|
|
462
|
+
vpConfig.head.push(["script", { src: `${server}/dist/Artalk.js`, id: "artalk-script" }]);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
456
466
|
function patchVPThemeConfig(cfg, vpThemeConfig = {}) {
|
|
457
467
|
vpThemeConfig.sidebar = patchDefaultThemeSideBar(cfg)?.sidebar;
|
|
458
468
|
return vpThemeConfig;
|
|
@@ -574,6 +584,7 @@ function getThemeConfig(cfg) {
|
|
|
574
584
|
registerMdPlugins(extraVPConfig, markdownPlugin);
|
|
575
585
|
patchMermaidPluginCfg(extraVPConfig);
|
|
576
586
|
patchOptimizeDeps(extraVPConfig);
|
|
587
|
+
patchVPConfig(extraVPConfig, cfg);
|
|
577
588
|
return {
|
|
578
589
|
themeConfig: {
|
|
579
590
|
blog: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,12 +52,13 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@element-plus/icons-vue": "^2.1.0",
|
|
55
|
+
"artalk": "^2.8.3",
|
|
55
56
|
"element-plus": "^2.3.4",
|
|
56
57
|
"javascript-stringify": "^2.1.0",
|
|
57
58
|
"pagefind": "1.0.3",
|
|
58
59
|
"sass": "^1.56.1",
|
|
59
60
|
"typescript": "^4.8.2",
|
|
60
|
-
"vitepress": "1.0.
|
|
61
|
+
"vitepress": "1.0.2",
|
|
61
62
|
"vue": "^3.4.21"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
@@ -7,8 +7,6 @@ import { useBlogThemeMode } from '../composables/config/blog'
|
|
|
7
7
|
import BlogHomeInfo from './BlogHomeInfo.vue'
|
|
8
8
|
import BlogHomeBanner from './BlogHomeBanner.vue'
|
|
9
9
|
import BlogList from './BlogList.vue'
|
|
10
|
-
import BlogComment from './BlogComment.vue'
|
|
11
|
-
|
|
12
10
|
import BlogSidebar from './BlogSidebar.vue'
|
|
13
11
|
import BlogImagePreview from './BlogImagePreview.vue'
|
|
14
12
|
import BlogArticleAnalyze from './BlogArticleAnalyze.vue'
|
|
@@ -17,6 +15,11 @@ import BlogPopover from './BlogPopover.vue'
|
|
|
17
15
|
import BlogFooter from './BlogFooter.vue'
|
|
18
16
|
import BlogHomeHeaderAvatar from './BlogHomeHeaderAvatar.vue'
|
|
19
17
|
import BlogBackToTop from './BlogBackToTop.vue'
|
|
18
|
+
import CommentGiscus from './CommentGiscus.vue'
|
|
19
|
+
|
|
20
|
+
import CommentArtalk from './CommentArtalk.vue'
|
|
21
|
+
import BlogButtonAfterArticle from './BlogButtonAfterArticle.vue'
|
|
22
|
+
import BlogCommentWrapper from './BlogCommentWrapper.vue'
|
|
20
23
|
|
|
21
24
|
const { frontmatter } = useData()
|
|
22
25
|
const layout = computed(() => frontmatter.value.layout)
|
|
@@ -74,8 +77,12 @@ useOml2d()
|
|
|
74
77
|
<slot name="doc-after" />
|
|
75
78
|
<!-- 评论 -->
|
|
76
79
|
<ClientOnly>
|
|
80
|
+
<BlogButtonAfterArticle />
|
|
77
81
|
<BlogBackToTop />
|
|
78
|
-
<
|
|
82
|
+
<BlogCommentWrapper>
|
|
83
|
+
<CommentArtalk />
|
|
84
|
+
<CommentGiscus />
|
|
85
|
+
</BlogCommentWrapper>
|
|
79
86
|
</ClientOnly>
|
|
80
87
|
</template>
|
|
81
88
|
<template #layout-bottom>
|
|
@@ -191,6 +198,7 @@ useOml2d()
|
|
|
191
198
|
.blog-list-wrapper {
|
|
192
199
|
width: 100%;
|
|
193
200
|
}
|
|
201
|
+
|
|
194
202
|
.blog-info-wrapper {
|
|
195
203
|
margin-left: 16px;
|
|
196
204
|
position: sticky;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ElButton } from 'element-plus'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
|
+
import { useData } from 'vitepress'
|
|
5
|
+
import { useBlogConfig } from '../composables/config/blog'
|
|
6
|
+
import { aliPaySVG, weChatPaySVG } from '../constants/svg'
|
|
7
|
+
|
|
8
|
+
const { buttonAfterArticle: _buttonAfterArticle } = useBlogConfig()
|
|
9
|
+
const { frontmatter } = useData()
|
|
10
|
+
const frontmatterConfig = computed(() => frontmatter.value.buttonAfterArticle)
|
|
11
|
+
|
|
12
|
+
const buttonAfterArticleConfig = computed(() => {
|
|
13
|
+
if (frontmatterConfig.value === false || (!frontmatterConfig.value && !_buttonAfterArticle)) {
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return { ..._buttonAfterArticle, ...frontmatterConfig.value }
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const showContent = ref(false)
|
|
21
|
+
|
|
22
|
+
watch(buttonAfterArticleConfig, () => {
|
|
23
|
+
showContent.value = !!buttonAfterArticleConfig.value?.expand
|
|
24
|
+
}, {
|
|
25
|
+
immediate: true
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const svg = computed(() => {
|
|
29
|
+
const icon = buttonAfterArticleConfig.value?.icon
|
|
30
|
+
if (icon === 'aliPay') {
|
|
31
|
+
return aliPaySVG
|
|
32
|
+
}
|
|
33
|
+
else if (icon === 'wechatPay') {
|
|
34
|
+
return weChatPaySVG
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return icon as string
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
function toggleContent() {
|
|
42
|
+
showContent.value = !showContent.value
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template>
|
|
47
|
+
<div v-if="buttonAfterArticleConfig" class="appreciation-container">
|
|
48
|
+
<ElButton :size="buttonAfterArticleConfig.size || 'default'" class="content-button" :type="showContent ? 'danger' : 'primary'" @click="toggleContent">
|
|
49
|
+
<span class="content-icon" v-html="svg" />
|
|
50
|
+
{{ showContent ? buttonAfterArticleConfig.closeTitle : buttonAfterArticleConfig.openTitle }}
|
|
51
|
+
</ElButton>
|
|
52
|
+
<transition name="content">
|
|
53
|
+
<div v-if="showContent" class="content-container" v-html="buttonAfterArticleConfig.content" />
|
|
54
|
+
</transition>
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<style scoped lang="scss">
|
|
59
|
+
.appreciation-container {
|
|
60
|
+
text-align: center;
|
|
61
|
+
padding: 20px;
|
|
62
|
+
font-size: 14px;
|
|
63
|
+
color: #606266;
|
|
64
|
+
|
|
65
|
+
:deep(.el-button.el-button--primary){
|
|
66
|
+
background-color: var(--vp-c-brand-2);
|
|
67
|
+
border-color: var(--vp-c-brand-2);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.content-container {
|
|
72
|
+
position: relative;
|
|
73
|
+
display: flex;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
align-items: center;
|
|
76
|
+
margin-top: 20px;
|
|
77
|
+
:deep(img){
|
|
78
|
+
height: 260px;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.content-icon {
|
|
83
|
+
font-family: "iconfont" !important;
|
|
84
|
+
font-size: 16px;
|
|
85
|
+
margin-right: 8px;
|
|
86
|
+
font-style: normal;
|
|
87
|
+
-webkit-font-smoothing: antialiased;
|
|
88
|
+
-moz-osx-font-smoothing: grayscale;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* 进入动画 */
|
|
92
|
+
.content-enter-active {
|
|
93
|
+
animation: fadeIn 0.5s ease forwards;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* 离开动画 */
|
|
97
|
+
.content-leave-active {
|
|
98
|
+
animation: fadeOut 0.3s ease forwards;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* 淡入 */
|
|
102
|
+
@keyframes fadeIn {
|
|
103
|
+
from {
|
|
104
|
+
opacity: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
to {
|
|
108
|
+
opacity: 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* 淡出 */
|
|
113
|
+
@keyframes fadeOut {
|
|
114
|
+
from {
|
|
115
|
+
opacity: 1;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
to {
|
|
119
|
+
opacity: 0;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
</style>
|
|
@@ -1,66 +1,33 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useElementSize, useElementVisibility, useWindowSize } from '@vueuse/core'
|
|
3
|
-
import { useData
|
|
4
|
-
import { computed, h, ref
|
|
3
|
+
import { useData } from 'vitepress'
|
|
4
|
+
import { computed, h, ref } from 'vue'
|
|
5
5
|
import { ElIcon } from 'element-plus'
|
|
6
6
|
import { Comment } from '@element-plus/icons-vue'
|
|
7
|
-
import
|
|
8
|
-
import { useGiscusConfig } from '../composables/config/blog'
|
|
9
|
-
import type { Theme } from '../composables/config/index'
|
|
7
|
+
import { useBlogConfig } from '../composables/config/blog'
|
|
10
8
|
|
|
11
9
|
const { frontmatter } = useData()
|
|
12
10
|
const commentEl = ref(null)
|
|
13
11
|
const commentIsVisible = useElementVisibility(commentEl)
|
|
14
12
|
|
|
15
13
|
function handleScrollToComment() {
|
|
16
|
-
document.querySelector('#
|
|
14
|
+
document.querySelector('#blog-comment-wrapper')?.scrollIntoView({
|
|
17
15
|
behavior: 'smooth',
|
|
18
16
|
block: 'start'
|
|
19
17
|
})
|
|
20
18
|
}
|
|
21
|
-
const giscusConfig = useGiscusConfig()
|
|
22
19
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return giscusConfig
|
|
28
|
-
})
|
|
20
|
+
const { comment: _comment } = useBlogConfig()
|
|
21
|
+
const commentConfig = computed(() =>
|
|
22
|
+
_comment === false ? undefined : _comment
|
|
23
|
+
)
|
|
29
24
|
|
|
30
25
|
const show = computed(() => {
|
|
31
|
-
|
|
32
|
-
return frontmatter.value.comment
|
|
33
|
-
}
|
|
34
|
-
if (!giscusConfig) {
|
|
35
|
-
return giscusConfig
|
|
36
|
-
}
|
|
37
|
-
return (
|
|
38
|
-
giscusConfig.repo
|
|
39
|
-
&& giscusConfig.repoId
|
|
40
|
-
&& giscusConfig.category
|
|
41
|
-
&& giscusConfig.categoryId
|
|
42
|
-
)
|
|
26
|
+
return _comment && frontmatter.value.comment !== false
|
|
43
27
|
})
|
|
44
28
|
|
|
45
|
-
const { isDark } = useData()
|
|
46
|
-
|
|
47
|
-
const route = useRoute()
|
|
48
|
-
const showComment = ref(true)
|
|
49
|
-
watch(
|
|
50
|
-
() => route.path,
|
|
51
|
-
() => {
|
|
52
|
-
showComment.value = false
|
|
53
|
-
setTimeout(() => {
|
|
54
|
-
showComment.value = true
|
|
55
|
-
}, 200)
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
immediate: true
|
|
59
|
-
}
|
|
60
|
-
)
|
|
61
|
-
|
|
62
29
|
const { width } = useWindowSize()
|
|
63
|
-
const mobileMinify = computed(() => width.value < 768 && (commentConfig.value
|
|
30
|
+
const mobileMinify = computed(() => width.value < 768 && (commentConfig.value?.mobileMinify ?? true))
|
|
64
31
|
|
|
65
32
|
const CommentIcon = commentConfig.value?.icon
|
|
66
33
|
? h('i', {
|
|
@@ -78,20 +45,13 @@ const { width: _docWidth } = useElementSize(el)
|
|
|
78
45
|
const docWidth = computed(() => `${_docWidth.value}px`)
|
|
79
46
|
|
|
80
47
|
const labelText = computed(() => {
|
|
81
|
-
return commentConfig.value
|
|
48
|
+
return commentConfig.value?.label ?? '评论'
|
|
82
49
|
})
|
|
83
50
|
</script>
|
|
84
51
|
|
|
85
52
|
<template>
|
|
86
|
-
<div v-if="show && _docWidth" id="
|
|
87
|
-
<
|
|
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'"
|
|
93
|
-
/>
|
|
94
|
-
|
|
53
|
+
<div v-if="show && _docWidth" id="blog-comment-wrapper" ref="commentEl" class="blog-comment-wrapper" data-pagefind-ignore="all">
|
|
54
|
+
<slot />
|
|
95
55
|
<div v-show="!commentIsVisible" class="comment-btn-wrapper">
|
|
96
56
|
<span v-if="!mobileMinify && labelText" class="icon-wrapper-text" @click="handleScrollToComment">
|
|
97
57
|
<ElIcon :size="20">
|
|
@@ -151,7 +111,7 @@ const labelText = computed(() => {
|
|
|
151
111
|
border-radius: 2px;
|
|
152
112
|
padding: 2px 6px;
|
|
153
113
|
|
|
154
|
-
span.text{
|
|
114
|
+
span.text {
|
|
155
115
|
font-size: 12px;
|
|
156
116
|
margin-left: 4px;
|
|
157
117
|
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
const route = useRoute()
|
|
14
14
|
const docs = useArticles()
|
|
15
|
-
const showTags = useConfig()?.config?.blog?.homeTags ??
|
|
15
|
+
const showTags = useConfig()?.config?.blog?.homeTags ?? true
|
|
16
16
|
const tags = computed(() => {
|
|
17
17
|
return [...new Set(docs.value.map(v => v.meta.tag || []).flat(3))]
|
|
18
18
|
})
|
|
@@ -166,7 +166,8 @@ const link = computed(() => withBase(wrapperCleanUrls(!!cleanUrls, props.route))
|
|
|
166
166
|
margin-left: 24px;
|
|
167
167
|
border-radius: 2px;
|
|
168
168
|
background-repeat: no-repeat;
|
|
169
|
-
background-size:
|
|
169
|
+
background-size: contain;
|
|
170
|
+
background-position: center;
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
.pc-visible {
|
|
@@ -181,7 +182,8 @@ const link = computed(() => withBase(wrapperCleanUrls(!!cleanUrls, props.route))
|
|
|
181
182
|
.cover-img {
|
|
182
183
|
width: 100px;
|
|
183
184
|
height: 60px;
|
|
184
|
-
background-size:
|
|
185
|
+
background-size: contain;
|
|
186
|
+
background-position: center;
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
.pc-visible {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
3
|
+
import { useData, useRoute } from 'vitepress'
|
|
4
|
+
import type Artalk from 'artalk'
|
|
5
|
+
|
|
6
|
+
import { useBlogConfig } from '../composables/config/blog'
|
|
7
|
+
|
|
8
|
+
const { isDark, page } = useData()
|
|
9
|
+
const el = ref<HTMLDivElement>()
|
|
10
|
+
|
|
11
|
+
const route = useRoute()
|
|
12
|
+
|
|
13
|
+
const artalk = ref<Artalk>()
|
|
14
|
+
|
|
15
|
+
const { comment } = useBlogConfig()
|
|
16
|
+
const commentConfig = computed(() => {
|
|
17
|
+
if (comment && 'type' in comment && comment.type === 'artalk') {
|
|
18
|
+
return comment.options
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
onMounted(() => {
|
|
25
|
+
// CDN 异步加载,有优化空间
|
|
26
|
+
const observer = new MutationObserver((mutationsList, observer) => {
|
|
27
|
+
if (window.Artalk && commentConfig.value && el.value) {
|
|
28
|
+
artalk.value = window.Artalk.init({
|
|
29
|
+
el: el.value,
|
|
30
|
+
darkMode: isDark.value,
|
|
31
|
+
pageKey: route.path,
|
|
32
|
+
pageTitle: page.value.title,
|
|
33
|
+
server: commentConfig.value?.server,
|
|
34
|
+
site: commentConfig.value?.site,
|
|
35
|
+
})
|
|
36
|
+
observer.disconnect()
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
observer.observe(document.head, { subtree: true, childList: true, attributes: true, attributeFilter: ['id'] })
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
watch(() => route.path, () => {
|
|
44
|
+
if (artalk.value) {
|
|
45
|
+
artalk.value.update({
|
|
46
|
+
pageKey: route.path,
|
|
47
|
+
pageTitle: page.value.title,
|
|
48
|
+
})
|
|
49
|
+
artalk.value.reload()
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
onUnmounted(() => {
|
|
54
|
+
if (artalk.value) {
|
|
55
|
+
artalk.value.destroy()
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
watch(isDark, () => {
|
|
60
|
+
if (artalk.value) {
|
|
61
|
+
artalk.value.setDarkMode(isDark.value)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<template>
|
|
67
|
+
<div v-if="commentConfig" ref="el" class="artalk-container" />
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<style lang="scss" scoped>
|
|
71
|
+
.artalk-container {
|
|
72
|
+
--at-color-main: var(--vp-c-brand-2);
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useData, useRoute } from 'vitepress'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
|
+
import Giscus from '@giscus/vue'
|
|
5
|
+
import { useBlogConfig } from '../composables/config/blog'
|
|
6
|
+
|
|
7
|
+
// 读取配制
|
|
8
|
+
const { comment } = useBlogConfig()
|
|
9
|
+
const commentConfig = computed(() => {
|
|
10
|
+
if (!comment) {
|
|
11
|
+
return false
|
|
12
|
+
}
|
|
13
|
+
if ('type' in comment && comment.type === 'giscus') {
|
|
14
|
+
return comment.options
|
|
15
|
+
}
|
|
16
|
+
else if (!('type' in comment)) {
|
|
17
|
+
return comment
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return false
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const { isDark } = useData()
|
|
24
|
+
|
|
25
|
+
const route = useRoute()
|
|
26
|
+
const showComment = ref(true)
|
|
27
|
+
watch(
|
|
28
|
+
() => route.path,
|
|
29
|
+
() => {
|
|
30
|
+
showComment.value = false
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
showComment.value = true
|
|
33
|
+
}, 200)
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
immediate: true
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<Giscus
|
|
43
|
+
v-if="commentConfig" :repo="commentConfig.repo" :repo-id="commentConfig.repoId"
|
|
44
|
+
:category="commentConfig.category" :category-id="commentConfig.categoryId"
|
|
45
|
+
:mapping="commentConfig.mapping || 'pathname'" reactions-enabled="1" emit-metadata="0"
|
|
46
|
+
:input-position="commentConfig.inputPosition || 'top'" :theme="isDark ? 'dark' : 'light'"
|
|
47
|
+
:lang="commentConfig.lang || 'zh-CN'" :loading="commentConfig.loading || 'eager'"
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
@@ -108,11 +108,6 @@ export function useBlogThemeMode() {
|
|
|
108
108
|
return inject(configSymbol)!.value?.blog?.blog ?? true
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
export function useGiscusConfig() {
|
|
112
|
-
const blogConfig = useConfig()
|
|
113
|
-
return blogConfig.config?.blog?.comment
|
|
114
|
-
}
|
|
115
|
-
|
|
116
111
|
export function useArticles() {
|
|
117
112
|
const blogConfig = useConfig()
|
|
118
113
|
const articles = computed(() => blogConfig.config?.blog?.pagesData || [])
|
|
@@ -100,7 +100,9 @@ export namespace Theme {
|
|
|
100
100
|
type: string
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
export
|
|
103
|
+
export type CommentConfig = ((GiscusOption & CommentCommonConfig) | GiscusConfig | ArtalkConfig)
|
|
104
|
+
|
|
105
|
+
export interface CommentCommonConfig {
|
|
104
106
|
/**
|
|
105
107
|
* @default '评论'
|
|
106
108
|
*/
|
|
@@ -116,7 +118,15 @@ export namespace Theme {
|
|
|
116
118
|
*/
|
|
117
119
|
mobileMinify?: boolean
|
|
118
120
|
}
|
|
119
|
-
export interface GiscusConfig {
|
|
121
|
+
export interface GiscusConfig extends CommentCommonConfig {
|
|
122
|
+
type: 'giscus'
|
|
123
|
+
options: GiscusOption
|
|
124
|
+
}
|
|
125
|
+
export interface ArtalkConfig extends CommentCommonConfig {
|
|
126
|
+
type: 'artalk'
|
|
127
|
+
options: ArtalkOption
|
|
128
|
+
}
|
|
129
|
+
export interface GiscusOption {
|
|
120
130
|
repo: Repo
|
|
121
131
|
repoId: string
|
|
122
132
|
category: string
|
|
@@ -126,6 +136,10 @@ export namespace Theme {
|
|
|
126
136
|
lang?: string
|
|
127
137
|
loading?: 'lazy' | 'eager'
|
|
128
138
|
}
|
|
139
|
+
export interface ArtalkOption {
|
|
140
|
+
site: string
|
|
141
|
+
server: string
|
|
142
|
+
}
|
|
129
143
|
|
|
130
144
|
export interface HotArticle {
|
|
131
145
|
title?: string
|
|
@@ -351,7 +365,8 @@ export namespace Theme {
|
|
|
351
365
|
search?: SearchConfig
|
|
352
366
|
/**
|
|
353
367
|
* 配置评论
|
|
354
|
-
*
|
|
368
|
+
* giscus: https://giscus.app/zh-CN
|
|
369
|
+
* artalk: https://artalk.js.org/
|
|
355
370
|
*/
|
|
356
371
|
comment?: CommentConfig | false
|
|
357
372
|
/**
|
|
@@ -424,6 +439,7 @@ export namespace Theme {
|
|
|
424
439
|
*/
|
|
425
440
|
oml2d?: Oml2dOptions
|
|
426
441
|
homeTags?: boolean
|
|
442
|
+
buttonAfterArticle?: ButtonAfterArticleConfig | false
|
|
427
443
|
}
|
|
428
444
|
|
|
429
445
|
export interface BackToTop {
|
|
@@ -509,4 +525,20 @@ export namespace Theme {
|
|
|
509
525
|
*/
|
|
510
526
|
handleChangeSlogan?: (oldSlogan: string) => string | Promise<string>
|
|
511
527
|
}
|
|
528
|
+
export interface ButtonAfterArticleConfig {
|
|
529
|
+
openTitle?: string
|
|
530
|
+
closeTitle?: string
|
|
531
|
+
content?: string
|
|
532
|
+
icon?: 'aliPay' | 'wechatPay' | string
|
|
533
|
+
/**
|
|
534
|
+
* 按钮尺寸
|
|
535
|
+
* @default 'default'
|
|
536
|
+
*/
|
|
537
|
+
size?: 'small' | 'default' | 'large'
|
|
538
|
+
/**
|
|
539
|
+
* 默认展开
|
|
540
|
+
* @default false
|
|
541
|
+
*/
|
|
542
|
+
expand?: boolean
|
|
543
|
+
}
|
|
512
544
|
}
|
package/src/constants/svg.ts
CHANGED
|
@@ -52,3 +52,26 @@ export const themeSVG = `<svg width="128" height="128" viewBox="0 0 24 24" xmlns
|
|
|
52
52
|
export const icpSVG = '<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" data-v-2f084f89=""><title data-v-2f084f89="">ICP备案号</title><path d="M778.24 163.84c-76.8-40.96-165.888-61.44-269.312-61.44s-192.512 20.48-269.312 61.44h-133.12l23.552 337.92c8.192 113.664 67.584 217.088 162.816 280.576l215.04 144.384 215.04-144.384c96.256-63.488 155.648-166.912 163.84-280.576l23.552-337.92H778.24z m47.104 333.824c-7.168 94.208-56.32 181.248-135.168 233.472l-181.248 120.832L327.68 731.136c-78.848-53.248-129.024-139.264-135.168-233.472L173.056 225.28h136.192v-26.624c58.368-23.552 124.928-34.816 199.68-34.816s141.312 12.288 199.68 34.816V225.28H844.8l-19.456 272.384z" data-v-2f084f89=""></path><path d="M685.056 328.704v-46.08H455.68c2.048-4.096 6.144-9.216 11.264-15.36 5.12-7.168 9.216-12.288 11.264-15.36L419.84 240.64c-31.744 46.08-75.776 87.04-133.12 123.904 4.096 4.096 10.24 11.264 18.432 21.504l17.408 17.408c23.552-15.36 45.056-31.744 63.488-50.176 26.624 25.6 49.152 43.008 67.584 51.2-46.08 15.36-104.448 27.648-175.104 35.84 2.048 5.12 6.144 13.312 9.216 24.576 4.096 11.264 6.144 19.456 7.168 24.576l39.936-7.168v218.112H389.12V680.96h238.592v19.456h54.272V481.28H348.16c60.416-12.288 114.688-27.648 163.84-46.08 49.152 19.456 118.784 34.816 210.944 46.08 5.12-17.408 10.24-34.816 17.408-51.2-62.464-4.096-116.736-12.288-161.792-24.576 38.912-20.48 74.752-46.08 106.496-76.8z m-150.528 194.56h94.208v41.984h-94.208v-41.984z m0 78.848h94.208v41.984h-94.208v-41.984z m-144.384-78.848h94.208v41.984H390.144v-41.984z m0 78.848h94.208v41.984H390.144v-41.984zM424.96 326.656h182.272c-26.624 22.528-57.344 41.984-94.208 57.344-31.744-15.36-61.44-34.816-88.064-57.344z" data-v-2f084f89=""></path></svg>'
|
|
53
53
|
|
|
54
54
|
export const copyrightSVG = '<svg t="1695543755857" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="89399" width="200" height="200"><path d="M512 16C238.066 16 16 238.066 16 512s222.066 496 496 496 496-222.066 496-496S785.934 16 512 16z m234.268 693.506c-3.184 3.734-79.552 91.462-219.702 91.462-169.384 0-288.968-126.52-288.968-291.134 0-162.606 124.008-286.802 287.524-286.802 133.914 0 203.93 74.63 206.844 77.808a24 24 0 0 1 2.476 29.246l-44.76 69.31c-8.098 12.534-25.548 14.702-36.468 4.59-0.466-0.428-53.058-47.76-123.76-47.76-92.232 0-147.832 67.15-147.832 152.164 0 79.204 51.028 159.384 148.554 159.384 77.394 0 130.56-56.676 131.088-57.25 10.264-11.13 28.118-10.066 37.016 2.106l49.094 67.144a24.002 24.002 0 0 1-1.106 29.732z" p-id="89400"></path></svg>'
|
|
55
|
+
|
|
56
|
+
export const aliPaySVG = `
|
|
57
|
+
<svg
|
|
58
|
+
id="mx_n_1711731519286" t="1711731519285" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
|
59
|
+
xmlns="http://www.w3.org/2000/svg" p-id="9945" width="16" height="16"
|
|
60
|
+
>
|
|
61
|
+
<path
|
|
62
|
+
d="M230.404 576.536c-12.087 9.728-25.043 23.93-28.805 41.984-5.12 24.666-1.069 55.541 22.728 79.761 28.828 29.362 72.637 37.398 91.56 38.779 51.4 3.717 106.184-21.772 147.477-50.844 16.184-11.42 43.899-34.349 70.39-69.721-59.37-30.653-133.477-64.557-212.703-61.24-40.47 1.692-69.454 10.084-90.647 21.281z m752.859 135.545C1009.463 650.574 1024 582.968 1024 512 1024 229.688 794.335 0 512 0 229.665 0 0 229.688 0 512c0 282.335 229.665 512 512 512 170.385 0 321.491-83.723 414.631-212.124-87.997-43.742-233.027-115.734-322.36-159.299-42.63 48.596-105.65 97.303-176.84 118.495-44.722 13.29-85.037 18.365-127.199 9.75-41.739-8.548-72.481-28.093-90.401-47.683-9.127-9.995-19.612-22.706-27.203-37.82a71.25 71.25 0 0 0 1.202 3.049s-4.363-7.524-7.702-19.5a85.994 85.994 0 0 1-3.34-18.143 93.517 93.517 0 0 1-0.2-13.045c-0.378-7.702-0.066-15.783 1.67-24.064 4.185-20.235 12.822-43.81 35.172-65.692 49.063-48.039 114.777-50.621 148.814-50.42 50.421 0.289 138.04 22.35 211.812 48.439 20.436-43.52 33.547-90.068 42.007-121.1H305.308v-33.168h157.518v-66.337H272.139v-33.169h190.687v-66.315c0-9.105 1.803-16.584 16.584-16.584h74.619v82.899h207.293v33.169H554.029v66.337h165.82s-16.65 92.828-68.719 184.32c115.557 41.272 278.128 104.849 332.133 126.086z"
|
|
63
|
+
fill="white" p-id="9946"
|
|
64
|
+
/>
|
|
65
|
+
</svg>
|
|
66
|
+
`
|
|
67
|
+
export const weChatPaySVG = `
|
|
68
|
+
<svg
|
|
69
|
+
t="1711730357270" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
|
70
|
+
p-id="4392" width="16" height="16"
|
|
71
|
+
>
|
|
72
|
+
<path
|
|
73
|
+
d="M512 1024a512 512 0 1 1 512-512 512 512 0 0 1-512 512z m-112.523636-836.538182c-144.989091 0-262.516364 100.538182-262.516364 224.465455 0 74.007273 42.123636 139.636364 106.705455 180.363636l-19.549091 78.312727 86.807272-47.592727a301.265455 301.265455 0 0 0 88.669091 13.381818h2.210909a178.967273 178.967273 0 0 1-3.607272-34.909091c0-115.083636 109.498182-208.407273 244.363636-208.407272 6.167273 0 11.636364 0 18.152727 0.814545-10.589091-115.665455-123.461818-206.778182-261.469091-206.778182z m246.690909 226.443637c-124.741818 0-225.861818 86.109091-225.861818 192.465454s101.003636 192.349091 225.861818 192.349091a257.047273 257.047273 0 0 0 99.723636-20.014545l77.265455 40.610909L802.909091 744.727273a179.316364 179.316364 0 0 0 69.003636-138.24c0-106.24-101.12-192.465455-225.861818-192.465455z m81.454545 152.087272a31.767273 31.767273 0 1 1 32.349091-31.767272 32 32 0 0 1-32.349091 31.767272z m-164.072727 0a31.767273 31.767273 0 1 1 32.349091-31.767272 32 32 0 0 1-32.349091 31.767272zM502.341818 373.527273a34.909091 34.909091 0 1 1 34.909091-34.909091 34.909091 34.909091 0 0 1-34.909091 34.909091z m-206.196363 0a34.909091 34.909091 0 1 1 34.90909-34.909091 34.909091 34.909091 0 0 1-34.90909 34.909091z m0 0"
|
|
74
|
+
fill="white" p-id="4393"
|
|
75
|
+
/>
|
|
76
|
+
</svg>
|
|
77
|
+
`
|
package/src/node.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
patchOptimizeDeps,
|
|
7
7
|
registerMdPlugins,
|
|
8
8
|
} from './utils/node/mdPlugins'
|
|
9
|
-
import { checkConfig, getArticles, patchVPThemeConfig } from './utils/node/theme'
|
|
9
|
+
import { checkConfig, getArticles, patchVPConfig, patchVPThemeConfig } from './utils/node/theme'
|
|
10
10
|
import { getVitePlugins, registerVitePlugins } from './utils/node/vitePlugins'
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -34,6 +34,8 @@ export function getThemeConfig(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
34
34
|
// patch extraVPConfig
|
|
35
35
|
patchMermaidPluginCfg(extraVPConfig)
|
|
36
36
|
patchOptimizeDeps(extraVPConfig)
|
|
37
|
+
|
|
38
|
+
patchVPConfig(extraVPConfig, cfg)
|
|
37
39
|
return {
|
|
38
40
|
themeConfig: {
|
|
39
41
|
blog: {
|
package/src/utils/node/theme.ts
CHANGED
|
@@ -125,7 +125,15 @@ export function getArticles(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
export function patchVPConfig(vpConfig: any, cfg?: Partial<Theme.BlogConfig>) {
|
|
128
|
-
|
|
128
|
+
vpConfig.head = vpConfig.head || []
|
|
129
|
+
// Artalk 资源地址
|
|
130
|
+
if (cfg?.comment && 'type' in cfg.comment && cfg?.comment?.type === 'artalk') {
|
|
131
|
+
const server = cfg.comment?.options?.server
|
|
132
|
+
if (server) {
|
|
133
|
+
vpConfig.head.push(['link', { href: `${server}/dist/Artalk.css`, rel: 'stylesheet' }])
|
|
134
|
+
vpConfig.head.push(['script', { src: `${server}/dist/Artalk.js`, id: 'artalk-script' }])
|
|
135
|
+
}
|
|
136
|
+
}
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
export function patchVPThemeConfig(
|
package/types/vue-shim.d.ts
CHANGED