@sugarat/theme 0.5.4 → 0.5.6
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 +7 -2
- package/node.js +22 -4
- package/node.mjs +22 -4
- package/package.json +5 -5
- package/src/components/BlogApp.vue +29 -2
- package/src/components/BlogArticleAnalyze.vue +42 -20
- package/src/components/BlogCommentWrapper.vue +2 -3
- package/src/components/UserWorks.vue +65 -81
- package/src/composables/config/blog.ts +5 -1
- package/src/composables/config/index.ts +7 -2
- package/src/index.ts +2 -2
- package/src/utils/node/mdPlugins.ts +3 -1
- package/src/utils/node/theme.ts +1 -1
- package/src/utils/node/vitePlugins.ts +19 -2
package/node.d.ts
CHANGED
|
@@ -181,6 +181,11 @@ declare namespace Theme {
|
|
|
181
181
|
* 首页数据分析卡片
|
|
182
182
|
*/
|
|
183
183
|
analysis?: HomeAnalysis;
|
|
184
|
+
/**
|
|
185
|
+
* 首页博客信息卡片是否在移动端折叠展示
|
|
186
|
+
* @default false
|
|
187
|
+
*/
|
|
188
|
+
blogInfoCollapsible?: boolean;
|
|
184
189
|
}
|
|
185
190
|
interface ArticleConfig {
|
|
186
191
|
/**
|
|
@@ -423,7 +428,7 @@ declare namespace Theme {
|
|
|
423
428
|
backToTop?: boolean | BackToTop;
|
|
424
429
|
/**
|
|
425
430
|
* oh-my-live2d 的 loadOml2d 方法的配置选项
|
|
426
|
-
* 详见 https://oml2d.
|
|
431
|
+
* 详见 https://oml2d.hacxy.cn/api/interfaces/Options.html
|
|
427
432
|
*/
|
|
428
433
|
oml2d?: Options;
|
|
429
434
|
homeTags?: boolean | HomeTagsConfig;
|
|
@@ -440,7 +445,7 @@ declare namespace Theme {
|
|
|
440
445
|
imageStyle?: ImageStyleConfig;
|
|
441
446
|
groupIcon?: {
|
|
442
447
|
customIcon: Record<string, string>;
|
|
443
|
-
};
|
|
448
|
+
} | false;
|
|
444
449
|
}
|
|
445
450
|
type FormatShowDate = {
|
|
446
451
|
/**
|
package/node.js
CHANGED
|
@@ -41,7 +41,7 @@ module.exports = __toCommonJS(node_exports);
|
|
|
41
41
|
// src/utils/node/mdPlugins.ts
|
|
42
42
|
var import_module = require("module");
|
|
43
43
|
|
|
44
|
-
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.6.3_@algolia+client-search@5.20.0_@types+node@
|
|
44
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.6.3_@algolia+client-search@5.20.0_@types+node@2_89d33a1149fc4afc3a4b1eeb07b93bba/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
45
45
|
var tabsMarker = "=tabs";
|
|
46
46
|
var tabsMarkerLen = tabsMarker.length;
|
|
47
47
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
|
@@ -289,7 +289,9 @@ function getMarkdownPlugins(cfg) {
|
|
|
289
289
|
if (cfg?.timeline !== false) {
|
|
290
290
|
markdownPlugin.push(import_vitepress_markdown_timeline.default);
|
|
291
291
|
}
|
|
292
|
-
|
|
292
|
+
if (cfg?.groupIcon !== false) {
|
|
293
|
+
markdownPlugin.push(import_vitepress_plugin_group_icons.groupIconMdPlugin);
|
|
294
|
+
}
|
|
293
295
|
return markdownPlugin;
|
|
294
296
|
}
|
|
295
297
|
function taskCheckboxPlugin(ops) {
|
|
@@ -397,7 +399,7 @@ async function getArticleMeta(filepath, route, timeZone = defaultTimeZoneOffset,
|
|
|
397
399
|
}
|
|
398
400
|
const utcValue = timeZone >= 0 ? `+${timeZone}` : `${timeZone}`;
|
|
399
401
|
const date = await (meta.date && /* @__PURE__ */ new Date(`${new Date(meta.date).toUTCString()}${utcValue}`) || (0, import_theme_shared2.getFileLastModifyTime)(filepath));
|
|
400
|
-
meta.date = formatDate(date || /* @__PURE__ */ new Date());
|
|
402
|
+
meta.date = formatDate(date || /* @__PURE__ */ new Date(), "yyyy/MM/dd hh:mm:ss");
|
|
401
403
|
meta.categories = typeof meta.categories === "string" ? [meta.categories] : meta.categories;
|
|
402
404
|
meta.tags = typeof meta.tags === "string" ? [meta.tags] : meta.tags;
|
|
403
405
|
meta.tag = [meta.tag || []].flat().concat([
|
|
@@ -566,9 +568,25 @@ function getVitePlugins(cfg = {}) {
|
|
|
566
568
|
if (cfg?.popover) {
|
|
567
569
|
plugins.push((0, import_vitepress_plugin_announcement.AnnouncementPlugin)(cfg.popover));
|
|
568
570
|
}
|
|
569
|
-
|
|
571
|
+
if (cfg?.groupIcon !== false) {
|
|
572
|
+
plugins.push(patchGroupIconPlugin());
|
|
573
|
+
plugins.push((0, import_vitepress_plugin_group_icons2.groupIconVitePlugin)(cfg?.groupIcon));
|
|
574
|
+
}
|
|
570
575
|
return plugins;
|
|
571
576
|
}
|
|
577
|
+
function patchGroupIconPlugin() {
|
|
578
|
+
return {
|
|
579
|
+
name: "@sugarat/theme-plugin-patch-group-icon",
|
|
580
|
+
enforce: "pre",
|
|
581
|
+
transform(code, id) {
|
|
582
|
+
if (id.match(/[\/\\]theme[\/\\]index\.(ts|js)$/)) {
|
|
583
|
+
return `import 'virtual:group-icons.css'
|
|
584
|
+
${code}`;
|
|
585
|
+
}
|
|
586
|
+
return code;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
572
590
|
function registerVitePlugins(vpCfg, plugins) {
|
|
573
591
|
vpCfg.vite = {
|
|
574
592
|
plugins,
|
package/node.mjs
CHANGED
|
@@ -9,7 +9,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
9
9
|
// src/utils/node/mdPlugins.ts
|
|
10
10
|
import { createRequire } from "module";
|
|
11
11
|
|
|
12
|
-
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.6.3_@algolia+client-search@5.20.0_@types+node@
|
|
12
|
+
// ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.6.3_@algolia+client-search@5.20.0_@types+node@2_89d33a1149fc4afc3a4b1eeb07b93bba/node_modules/vitepress-plugin-tabs/dist/index.js
|
|
13
13
|
var tabsMarker = "=tabs";
|
|
14
14
|
var tabsMarkerLen = tabsMarker.length;
|
|
15
15
|
var ruleBlockTabs = (state, startLine, endLine, silent) => {
|
|
@@ -256,7 +256,9 @@ function getMarkdownPlugins(cfg) {
|
|
|
256
256
|
if (cfg?.timeline !== false) {
|
|
257
257
|
markdownPlugin.push(timeline);
|
|
258
258
|
}
|
|
259
|
-
|
|
259
|
+
if (cfg?.groupIcon !== false) {
|
|
260
|
+
markdownPlugin.push(groupIconMdPlugin);
|
|
261
|
+
}
|
|
260
262
|
return markdownPlugin;
|
|
261
263
|
}
|
|
262
264
|
function taskCheckboxPlugin(ops) {
|
|
@@ -363,7 +365,7 @@ async function getArticleMeta(filepath, route, timeZone = defaultTimeZoneOffset,
|
|
|
363
365
|
}
|
|
364
366
|
const utcValue = timeZone >= 0 ? `+${timeZone}` : `${timeZone}`;
|
|
365
367
|
const date = await (meta.date && /* @__PURE__ */ new Date(`${new Date(meta.date).toUTCString()}${utcValue}`) || getFileLastModifyTime(filepath));
|
|
366
|
-
meta.date = formatDate(date || /* @__PURE__ */ new Date());
|
|
368
|
+
meta.date = formatDate(date || /* @__PURE__ */ new Date(), "yyyy/MM/dd hh:mm:ss");
|
|
367
369
|
meta.categories = typeof meta.categories === "string" ? [meta.categories] : meta.categories;
|
|
368
370
|
meta.tags = typeof meta.tags === "string" ? [meta.tags] : meta.tags;
|
|
369
371
|
meta.tag = [meta.tag || []].flat().concat([
|
|
@@ -534,9 +536,25 @@ function getVitePlugins(cfg = {}) {
|
|
|
534
536
|
if (cfg?.popover) {
|
|
535
537
|
plugins.push(AnnouncementPlugin(cfg.popover));
|
|
536
538
|
}
|
|
537
|
-
|
|
539
|
+
if (cfg?.groupIcon !== false) {
|
|
540
|
+
plugins.push(patchGroupIconPlugin());
|
|
541
|
+
plugins.push(groupIconVitePlugin(cfg?.groupIcon));
|
|
542
|
+
}
|
|
538
543
|
return plugins;
|
|
539
544
|
}
|
|
545
|
+
function patchGroupIconPlugin() {
|
|
546
|
+
return {
|
|
547
|
+
name: "@sugarat/theme-plugin-patch-group-icon",
|
|
548
|
+
enforce: "pre",
|
|
549
|
+
transform(code, id) {
|
|
550
|
+
if (id.match(/[\/\\]theme[\/\\]index\.(ts|js)$/)) {
|
|
551
|
+
return `import 'virtual:group-icons.css'
|
|
552
|
+
${code}`;
|
|
553
|
+
}
|
|
554
|
+
return code;
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
540
558
|
function registerVitePlugins(vpCfg, plugins) {
|
|
541
559
|
vpCfg.vite = {
|
|
542
560
|
plugins,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarat/theme",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
|
|
5
5
|
"author": "sugar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,12 +50,12 @@
|
|
|
50
50
|
"oh-my-live2d": "^0.19.3",
|
|
51
51
|
"swiper": "^11.1.1",
|
|
52
52
|
"vitepress-markdown-timeline": "^1.2.1",
|
|
53
|
-
"vitepress-plugin-group-icons": "
|
|
53
|
+
"vitepress-plugin-group-icons": "1.2.4",
|
|
54
54
|
"vitepress-plugin-mermaid": "2.0.13",
|
|
55
55
|
"vitepress-plugin-tabs": "0.2.0",
|
|
56
|
-
"@sugarat/theme-shared": "0.0.
|
|
57
|
-
"vitepress-plugin-announcement": "0.1.
|
|
58
|
-
"vitepress-plugin-pagefind": "0.4.
|
|
56
|
+
"@sugarat/theme-shared": "0.0.5",
|
|
57
|
+
"vitepress-plugin-announcement": "0.1.5",
|
|
58
|
+
"vitepress-plugin-pagefind": "0.4.14",
|
|
59
59
|
"vitepress-plugin-rss": "0.3.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
@@ -3,7 +3,7 @@ import Theme from 'vitepress/theme'
|
|
|
3
3
|
import { useData } from 'vitepress'
|
|
4
4
|
import { computed } from 'vue'
|
|
5
5
|
import { useDarkTransition } from '../hooks/useDarkTransition'
|
|
6
|
-
import { useBlogThemeMode, useDarkTransitionConfig } from '../composables/config/blog'
|
|
6
|
+
import { useBlogInfoCollapsible, useBlogThemeMode, useDarkTransitionConfig } 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'
|
|
@@ -26,6 +26,8 @@ const layout = computed(() => frontmatter.value.layout)
|
|
|
26
26
|
const isBlogTheme = useBlogThemeMode()
|
|
27
27
|
const { Layout } = Theme
|
|
28
28
|
|
|
29
|
+
const blogInfoCollapsible = useBlogInfoCollapsible()
|
|
30
|
+
|
|
29
31
|
// 切换深色模式过渡
|
|
30
32
|
// https://vitepress.dev/zh/guide/extending-default-theme#on-appearance-toggle
|
|
31
33
|
useDarkTransition()
|
|
@@ -67,7 +69,11 @@ const openTransition = useDarkTransitionConfig()
|
|
|
67
69
|
<div class="blog-list-wrapper">
|
|
68
70
|
<BlogList />
|
|
69
71
|
</div>
|
|
70
|
-
<div
|
|
72
|
+
<div
|
|
73
|
+
:class="{
|
|
74
|
+
'normal-mode': blogInfoCollapsible,
|
|
75
|
+
}" class="blog-info-wrapper"
|
|
76
|
+
>
|
|
71
77
|
<BlogHomeInfo />
|
|
72
78
|
</div>
|
|
73
79
|
</div>
|
|
@@ -108,6 +114,9 @@ const openTransition = useDarkTransitionConfig()
|
|
|
108
114
|
<slot name="nav-screen-content-before" />
|
|
109
115
|
</template>
|
|
110
116
|
<template #nav-screen-content-after>
|
|
117
|
+
<div v-if="blogInfoCollapsible" class="minify-mode blog-info-wrapper">
|
|
118
|
+
<BlogHomeInfo />
|
|
119
|
+
</div>
|
|
111
120
|
<slot name="nav-screen-content-after" />
|
|
112
121
|
</template>
|
|
113
122
|
|
|
@@ -226,6 +235,24 @@ const openTransition = useDarkTransitionConfig()
|
|
|
226
235
|
margin: 20px 0;
|
|
227
236
|
width: 100%;
|
|
228
237
|
}
|
|
238
|
+
|
|
239
|
+
.normal-mode {
|
|
240
|
+
display: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.minify-mode {
|
|
244
|
+
display: block;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@media screen and (min-width: 768px) {
|
|
249
|
+
.minify-mode {
|
|
250
|
+
display: none;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.normal-mode {
|
|
254
|
+
display: block;
|
|
255
|
+
}
|
|
229
256
|
}
|
|
230
257
|
</style>
|
|
231
258
|
|
|
@@ -131,24 +131,25 @@ const timeTitle = computed(() =>
|
|
|
131
131
|
<template>
|
|
132
132
|
<div v-if="showAnalyze && readingTimePosition === 'top'" class="doc-analyze" data-pagefind-ignore="all">
|
|
133
133
|
<span>
|
|
134
|
-
<ElIcon
|
|
134
|
+
<ElIcon>
|
|
135
|
+
<EditPen />
|
|
136
|
+
</ElIcon>
|
|
135
137
|
{{ topWordCount }}
|
|
136
138
|
</span>
|
|
137
139
|
<span>
|
|
138
|
-
<ElIcon
|
|
140
|
+
<ElIcon>
|
|
141
|
+
<AlarmClock />
|
|
142
|
+
</ElIcon>
|
|
139
143
|
{{ topReadTime }}
|
|
140
144
|
</span>
|
|
141
145
|
</div>
|
|
142
146
|
<div id="hack-article-des" ref="$des" class="meta-des">
|
|
143
147
|
<!-- TODO:是否需要原创?转载等标签,理论上可以添加标签解决,可以参考 charles7c -->
|
|
144
148
|
<span v-if="author && !hiddenAuthor" class="author" :title="authorTitle">
|
|
145
|
-
<ElIcon
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
:href="currentAuthorInfo.url"
|
|
150
|
-
:title="currentAuthorInfo.des"
|
|
151
|
-
>
|
|
149
|
+
<ElIcon>
|
|
150
|
+
<UserFilled />
|
|
151
|
+
</ElIcon>
|
|
152
|
+
<a v-if="currentAuthorInfo" class="link" :href="currentAuthorInfo.url" :title="currentAuthorInfo.des">
|
|
152
153
|
{{ currentAuthorInfo.nickname }}
|
|
153
154
|
</a>
|
|
154
155
|
<template v-else>
|
|
@@ -156,36 +157,48 @@ const timeTitle = computed(() =>
|
|
|
156
157
|
</template>
|
|
157
158
|
</span>
|
|
158
159
|
<span v-if="publishDate && !hiddenTime" class="publishDate" :title="timeTitle + hoverDate">
|
|
159
|
-
<ElIcon
|
|
160
|
+
<ElIcon>
|
|
161
|
+
<Clock />
|
|
162
|
+
</ElIcon>
|
|
160
163
|
{{ publishDate }}
|
|
161
164
|
</span>
|
|
162
|
-
<span v-if="tags.length" class="tags" :title="tagTitle">
|
|
163
|
-
<ElIcon><CollectionTag /></ElIcon>
|
|
164
|
-
<a v-for="tag in tags" :key="tag" class="link" :href="`/?tag=${tag}`">{{ tag }}
|
|
165
|
-
</a>
|
|
166
|
-
</span>
|
|
167
165
|
<template v-if="readingTimePosition === 'inline' && showAnalyze">
|
|
168
166
|
<span :title="wordCountTitle">
|
|
169
|
-
<ElIcon
|
|
167
|
+
<ElIcon>
|
|
168
|
+
<EditPen />
|
|
169
|
+
</ElIcon>
|
|
170
170
|
{{ inlineWordCount }}
|
|
171
171
|
</span>
|
|
172
172
|
<span :title="readTimeTitle">
|
|
173
|
-
<ElIcon
|
|
173
|
+
<ElIcon>
|
|
174
|
+
<AlarmClock />
|
|
175
|
+
</ElIcon>
|
|
174
176
|
{{ inlineReadTime }}
|
|
175
177
|
</span>
|
|
176
178
|
</template>
|
|
177
179
|
<template v-if="readingTimePosition === 'newLine' && showAnalyze">
|
|
178
180
|
<div style="width: 100%;" class="new-line-meta-des">
|
|
179
181
|
<span :title="wordCountTitle">
|
|
180
|
-
<ElIcon
|
|
182
|
+
<ElIcon>
|
|
183
|
+
<EditPen />
|
|
184
|
+
</ElIcon>
|
|
181
185
|
{{ inlineWordCount }}
|
|
182
186
|
</span>
|
|
183
187
|
<span :title="readTimeTitle">
|
|
184
|
-
<ElIcon
|
|
188
|
+
<ElIcon>
|
|
189
|
+
<AlarmClock />
|
|
190
|
+
</ElIcon>
|
|
185
191
|
{{ inlineReadTime }}
|
|
186
192
|
</span>
|
|
187
193
|
</div>
|
|
188
194
|
</template>
|
|
195
|
+
<span v-if="tags.length" class="tags" :title="tagTitle">
|
|
196
|
+
<ElIcon>
|
|
197
|
+
<CollectionTag />
|
|
198
|
+
</ElIcon>
|
|
199
|
+
<a v-for="tag in tags" :key="tag" class="link" :href="`/?tag=${tag}`">{{ tag }}
|
|
200
|
+
</a>
|
|
201
|
+
</span>
|
|
189
202
|
<!-- 封面展示 -->
|
|
190
203
|
<ClientOnly>
|
|
191
204
|
<BlogDocCover />
|
|
@@ -200,26 +213,33 @@ const timeTitle = computed(() =>
|
|
|
200
213
|
margin-bottom: 20px;
|
|
201
214
|
display: flex;
|
|
202
215
|
justify-content: center;
|
|
216
|
+
|
|
203
217
|
span {
|
|
204
218
|
margin-right: 16px;
|
|
205
219
|
display: flex;
|
|
206
220
|
align-items: center;
|
|
221
|
+
|
|
207
222
|
.el-icon {
|
|
208
223
|
margin-right: 4px;
|
|
209
224
|
}
|
|
210
225
|
}
|
|
211
226
|
}
|
|
212
|
-
|
|
227
|
+
|
|
228
|
+
.meta-des,
|
|
229
|
+
.new-line-meta-des {
|
|
213
230
|
text-align: left;
|
|
214
231
|
color: var(--vp-c-text-2);
|
|
215
232
|
font-size: 14px;
|
|
216
233
|
margin-top: 6px;
|
|
217
234
|
display: flex;
|
|
218
235
|
flex-wrap: wrap;
|
|
236
|
+
|
|
219
237
|
>span {
|
|
220
238
|
margin-right: 16px;
|
|
221
239
|
display: flex;
|
|
222
240
|
align-items: center;
|
|
241
|
+
flex-wrap: wrap;
|
|
242
|
+
|
|
223
243
|
.el-icon {
|
|
224
244
|
margin-right: 4px;
|
|
225
245
|
}
|
|
@@ -227,12 +247,14 @@ const timeTitle = computed(() =>
|
|
|
227
247
|
|
|
228
248
|
.link {
|
|
229
249
|
color: var(--vp-c-text-2);
|
|
250
|
+
|
|
230
251
|
&:hover {
|
|
231
252
|
color: var(--vp-c-brand-1);
|
|
232
253
|
cursor: pointer;
|
|
233
254
|
}
|
|
234
255
|
}
|
|
235
256
|
}
|
|
257
|
+
|
|
236
258
|
.tags {
|
|
237
259
|
a.link:not(:last-child) {
|
|
238
260
|
&::after {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useElementSize, useElementVisibility, useWindowSize } from '@vueuse/core'
|
|
3
3
|
import { computed, ref } from 'vue'
|
|
4
|
-
import { Comment } from '@element-plus/icons-vue'
|
|
5
4
|
import { useCommentConfig, useOpenCommentConfig } from '../composables/config/blog'
|
|
6
5
|
import Icon from './Icon.vue'
|
|
7
6
|
|
|
@@ -38,7 +37,7 @@ const labelText = computed(() => {
|
|
|
38
37
|
<div v-show="!commentIsVisible" class="comment-btn-wrapper">
|
|
39
38
|
<span v-if="!mobileMinify && labelText" class="icon-wrapper-text" @click="handleScrollToComment">
|
|
40
39
|
<Icon :size="20" :icon="commentConfig?.icon">
|
|
41
|
-
<
|
|
40
|
+
<svg data-v-f0aeb853="" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024"><path fill="currentColor" d="M736 504a56 56 0 1 1 0-112 56 56 0 0 1 0 112m-224 0a56 56 0 1 1 0-112 56 56 0 0 1 0 112m-224 0a56 56 0 1 1 0-112 56 56 0 0 1 0 112M128 128v640h192v160l224-160h352V128z" /></svg>
|
|
42
41
|
</Icon>
|
|
43
42
|
<span class="text">
|
|
44
43
|
{{ labelText }}
|
|
@@ -46,7 +45,7 @@ const labelText = computed(() => {
|
|
|
46
45
|
</span>
|
|
47
46
|
<span v-else class="icon-wrapper" @click="handleScrollToComment">
|
|
48
47
|
<Icon :size="20" :icon="commentConfig?.icon">
|
|
49
|
-
<
|
|
48
|
+
<svg data-v-f0aeb853="" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024"><path fill="currentColor" d="M736 504a56 56 0 1 1 0-112 56 56 0 0 1 0 112m-224 0a56 56 0 1 1 0-112 56 56 0 0 1 0 112m-224 0a56 56 0 1 1 0-112 56 56 0 0 1 0 112M128 128v640h192v160l224-160h352V128z" /></svg>
|
|
50
49
|
</Icon>
|
|
51
50
|
</span>
|
|
52
51
|
</div>
|
|
@@ -213,11 +213,7 @@ function handleChooseTag(tag: string) {
|
|
|
213
213
|
<!-- times -->
|
|
214
214
|
<div class="times">
|
|
215
215
|
<span class="icon">
|
|
216
|
-
<svg
|
|
217
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
218
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
219
|
-
viewBox="0 0 24 24"
|
|
220
|
-
>
|
|
216
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
|
|
221
217
|
<title>上线时间</title>
|
|
222
218
|
<path
|
|
223
219
|
d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8s8 3.58 8 8s-3.58 8-8 8zm-.22-13h-.06c-.4 0-.72.32-.72.72v4.72c0 .35.18.68.49.86l4.15 2.49c.34.2.78.1.98-.24a.71.71 0 0 0-.25-.99l-3.87-2.3V7.72c0-.4-.32-.72-.72-.72z"
|
|
@@ -230,17 +226,10 @@ function handleChooseTag(tag: string) {
|
|
|
230
226
|
</div>
|
|
231
227
|
<!-- GitHub links -->
|
|
232
228
|
<div v-if="work.github" class="links">
|
|
233
|
-
<a
|
|
234
|
-
v-if="work.github"
|
|
235
|
-
class="github-link"
|
|
236
|
-
:href="work.github as string"
|
|
237
|
-
target="_blank"
|
|
238
|
-
rel="noopener"
|
|
239
|
-
>
|
|
229
|
+
<a v-if="work.github" class="github-link" :href="work.github as string" target="_blank" rel="noopener">
|
|
240
230
|
<i class="icon">
|
|
241
231
|
<svg
|
|
242
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
243
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
232
|
+
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
244
233
|
viewBox="0 0 496 512"
|
|
245
234
|
>
|
|
246
235
|
<path
|
|
@@ -255,35 +244,16 @@ function handleChooseTag(tag: string) {
|
|
|
255
244
|
<!-- 其它自定义链接 -->
|
|
256
245
|
<div v-if="work.links?.length" class="links">
|
|
257
246
|
<i v-if="work.links?.length" class="icon">
|
|
258
|
-
<svg
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
>
|
|
263
|
-
<g
|
|
264
|
-
fill="none"
|
|
265
|
-
stroke="currentColor"
|
|
266
|
-
stroke-width="2"
|
|
267
|
-
stroke-linecap="round"
|
|
268
|
-
stroke-linejoin="round"
|
|
269
|
-
>
|
|
270
|
-
<path
|
|
271
|
-
d="M10 14a3.5 3.5 0 0 0 5 0l4-4a3.5 3.5 0 0 0-5-5l-.5.5"
|
|
272
|
-
/>
|
|
273
|
-
<path
|
|
274
|
-
d="M14 10a3.5 3.5 0 0 0-5 0l-4 4a3.5 3.5 0 0 0 5 5l.5-.5"
|
|
275
|
-
/>
|
|
247
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
|
|
248
|
+
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
249
|
+
<path d="M10 14a3.5 3.5 0 0 0 5 0l4-4a3.5 3.5 0 0 0-5-5l-.5.5" />
|
|
250
|
+
<path d="M14 10a3.5 3.5 0 0 0-5 0l-4 4a3.5 3.5 0 0 0 5 5l.5-.5" />
|
|
276
251
|
</g>
|
|
277
252
|
</svg>
|
|
278
253
|
</i>
|
|
279
254
|
<a
|
|
280
|
-
v-for="link in work.links || []"
|
|
281
|
-
|
|
282
|
-
class="link"
|
|
283
|
-
:href="link.url"
|
|
284
|
-
:title="link.title"
|
|
285
|
-
target="_blank"
|
|
286
|
-
rel="noopener"
|
|
255
|
+
v-for="link in work.links || []" :key="link.url" class="link" :href="link.url" :title="link.title"
|
|
256
|
+
target="_blank" rel="noopener"
|
|
287
257
|
>
|
|
288
258
|
{{ link.title }}
|
|
289
259
|
</a>
|
|
@@ -291,23 +261,14 @@ function handleChooseTag(tag: string) {
|
|
|
291
261
|
<!-- tags -->
|
|
292
262
|
<div v-if="work.tags?.length" class="tags">
|
|
293
263
|
<i class="icon">
|
|
294
|
-
<svg
|
|
295
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
296
|
-
viewBox="0 0 1024 1024"
|
|
297
|
-
data-v-d328c40a=""
|
|
298
|
-
>
|
|
264
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-d328c40a="">
|
|
299
265
|
<path
|
|
300
266
|
fill="currentColor"
|
|
301
267
|
d="M256 128v698.88l196.032-156.864a96 96 0 0 1 119.936 0L768 826.816V128H256zm-32-64h576a32 32 0 0 1 32 32v797.44a32 32 0 0 1-51.968 24.96L531.968 720a32 32 0 0 0-39.936 0L243.968 918.4A32 32 0 0 1 192 893.44V96a32 32 0 0 1 32-32z"
|
|
302
268
|
/>
|
|
303
269
|
</svg>
|
|
304
270
|
</i>
|
|
305
|
-
<span
|
|
306
|
-
v-for="tag in work.tags"
|
|
307
|
-
:key="tag"
|
|
308
|
-
class="tag"
|
|
309
|
-
@click="handleChooseTag(tag)"
|
|
310
|
-
>{{ tag }}
|
|
271
|
+
<span v-for="tag in work.tags" :key="tag" class="tag" @click="handleChooseTag(tag)">{{ tag }}
|
|
311
272
|
</span>
|
|
312
273
|
</div>
|
|
313
274
|
</div>
|
|
@@ -315,25 +276,11 @@ function handleChooseTag(tag: string) {
|
|
|
315
276
|
<div v-if="work.covers?.length" class="images">
|
|
316
277
|
<!-- swiper -->
|
|
317
278
|
<div v-if="work.coverLayout === 'swiper'" class="swiper-mode">
|
|
318
|
-
<ElCarousel
|
|
319
|
-
|
|
320
|
-
height="260px"
|
|
321
|
-
:type="isCardMode && work.covers.length >= 3 ? 'card' : ''"
|
|
322
|
-
>
|
|
323
|
-
<ElCarouselItem
|
|
324
|
-
v-for="(url, idx) in work.covers"
|
|
325
|
-
:key="url"
|
|
326
|
-
style="text-align: center"
|
|
327
|
-
>
|
|
279
|
+
<ElCarousel autoplay height="260px" :type="isCardMode && work.covers.length >= 3 ? 'card' : ''">
|
|
280
|
+
<ElCarouselItem v-for="(url, idx) in work.covers" :key="url" style="text-align: center">
|
|
328
281
|
<ElImage
|
|
329
|
-
:key="url"
|
|
330
|
-
|
|
331
|
-
:src="url"
|
|
332
|
-
loading="lazy"
|
|
333
|
-
:preview-src-list="work.covers"
|
|
334
|
-
:initial-index="idx"
|
|
335
|
-
hide-on-click-modal
|
|
336
|
-
:alt="`${work.title}-${idx}`"
|
|
282
|
+
:key="url" preview-teleported :src="url" loading="lazy" :preview-src-list="work.covers"
|
|
283
|
+
:initial-index="idx" hide-on-click-modal :alt="`${work.title}-${idx}`"
|
|
337
284
|
/>
|
|
338
285
|
</ElCarouselItem>
|
|
339
286
|
</ElCarousel>
|
|
@@ -341,13 +288,8 @@ function handleChooseTag(tag: string) {
|
|
|
341
288
|
<!-- list -->
|
|
342
289
|
<div v-if="work.coverLayout === 'list'" class="list-mode">
|
|
343
290
|
<ElImage
|
|
344
|
-
v-for="(url, idx) in work.covers"
|
|
345
|
-
:
|
|
346
|
-
:src="url"
|
|
347
|
-
loading="lazy"
|
|
348
|
-
:preview-src-list="work.covers"
|
|
349
|
-
:initial-index="idx"
|
|
350
|
-
hide-on-click-modal
|
|
291
|
+
v-for="(url, idx) in work.covers" :key="url" :src="url" loading="lazy"
|
|
292
|
+
:preview-src-list="work.covers" :initial-index="idx" hide-on-click-modal
|
|
351
293
|
/>
|
|
352
294
|
</div>
|
|
353
295
|
</div>
|
|
@@ -369,24 +311,29 @@ function handleChooseTag(tag: string) {
|
|
|
369
311
|
width: 100%;
|
|
370
312
|
margin: 20px auto;
|
|
371
313
|
padding: 16px;
|
|
314
|
+
|
|
372
315
|
h1 {
|
|
373
316
|
font-size: 32px;
|
|
374
317
|
font-weight: bold;
|
|
375
318
|
}
|
|
319
|
+
|
|
376
320
|
.description {
|
|
377
321
|
margin-top: 16px;
|
|
378
322
|
color: #999;
|
|
379
323
|
font-size: 16px;
|
|
380
324
|
}
|
|
325
|
+
|
|
381
326
|
a {
|
|
382
327
|
font-weight: 500;
|
|
383
328
|
color: var(--vp-c-brand-1);
|
|
384
329
|
}
|
|
385
330
|
}
|
|
331
|
+
|
|
386
332
|
.works-container {
|
|
387
333
|
display: flex;
|
|
388
334
|
justify-content: center;
|
|
389
335
|
}
|
|
336
|
+
|
|
390
337
|
.work {
|
|
391
338
|
max-width: 900px;
|
|
392
339
|
|
|
@@ -396,9 +343,11 @@ function handleChooseTag(tag: string) {
|
|
|
396
343
|
line-height: 32px;
|
|
397
344
|
font-size: 24px;
|
|
398
345
|
border-top: 1px solid var(--vp-c-divider);
|
|
346
|
+
|
|
399
347
|
a {
|
|
400
348
|
color: inherit;
|
|
401
349
|
}
|
|
350
|
+
|
|
402
351
|
&:hover {
|
|
403
352
|
a {
|
|
404
353
|
&::before {
|
|
@@ -406,8 +355,10 @@ function handleChooseTag(tag: string) {
|
|
|
406
355
|
}
|
|
407
356
|
}
|
|
408
357
|
}
|
|
358
|
+
|
|
409
359
|
a {
|
|
410
360
|
position: relative;
|
|
361
|
+
|
|
411
362
|
&::before {
|
|
412
363
|
position: absolute;
|
|
413
364
|
left: -16px;
|
|
@@ -416,37 +367,44 @@ function handleChooseTag(tag: string) {
|
|
|
416
367
|
}
|
|
417
368
|
}
|
|
418
369
|
}
|
|
370
|
+
|
|
419
371
|
h3 {
|
|
420
372
|
margin: 32px 0 0;
|
|
421
373
|
line-height: 28px;
|
|
422
374
|
font-size: 20px;
|
|
423
375
|
position: relative;
|
|
424
|
-
|
|
376
|
+
|
|
377
|
+
&.title>a.pin {
|
|
425
378
|
position: absolute;
|
|
426
379
|
left: -16px;
|
|
380
|
+
|
|
427
381
|
&::before {
|
|
428
382
|
left: -16px;
|
|
429
383
|
opacity: 0;
|
|
430
384
|
content: var(--vp-header-anchor-symbol);
|
|
431
385
|
}
|
|
432
386
|
}
|
|
433
|
-
|
|
387
|
+
|
|
388
|
+
&:hover>a.pin {
|
|
434
389
|
&::before {
|
|
435
390
|
opacity: 1;
|
|
436
391
|
}
|
|
437
392
|
}
|
|
438
393
|
}
|
|
394
|
+
|
|
439
395
|
.info {
|
|
440
396
|
display: flex;
|
|
441
397
|
font-size: 14px;
|
|
442
398
|
margin-top: 10px;
|
|
443
399
|
flex-wrap: wrap;
|
|
444
400
|
}
|
|
401
|
+
|
|
445
402
|
.links,
|
|
446
403
|
.times,
|
|
447
404
|
.tags {
|
|
448
405
|
display: flex;
|
|
449
406
|
align-items: center;
|
|
407
|
+
|
|
450
408
|
.icon {
|
|
451
409
|
color: var(--vp-c-text-1);
|
|
452
410
|
display: block;
|
|
@@ -455,34 +413,42 @@ function handleChooseTag(tag: string) {
|
|
|
455
413
|
margin-right: 6px;
|
|
456
414
|
}
|
|
457
415
|
}
|
|
416
|
+
|
|
458
417
|
.times {
|
|
459
418
|
margin-right: 18px;
|
|
460
419
|
}
|
|
420
|
+
|
|
461
421
|
.links {
|
|
462
422
|
a {
|
|
463
423
|
display: flex;
|
|
464
424
|
align-items: center;
|
|
465
425
|
}
|
|
426
|
+
|
|
466
427
|
a.github-link {
|
|
467
428
|
margin-right: 10px;
|
|
468
429
|
}
|
|
430
|
+
|
|
469
431
|
a.link {
|
|
470
432
|
margin-right: 0;
|
|
433
|
+
|
|
471
434
|
&::after {
|
|
472
435
|
content: ',';
|
|
473
436
|
color: var(--vp-c-text-1);
|
|
474
437
|
margin-right: 6px;
|
|
475
438
|
margin-left: 2px;
|
|
476
439
|
}
|
|
440
|
+
|
|
477
441
|
&:last-child::after {
|
|
478
442
|
content: '';
|
|
479
443
|
}
|
|
480
444
|
}
|
|
481
445
|
}
|
|
446
|
+
|
|
482
447
|
.tags {
|
|
483
448
|
span.tag {
|
|
484
449
|
cursor: pointer;
|
|
485
450
|
}
|
|
451
|
+
|
|
486
452
|
span.tag:not(:last-child) {
|
|
487
453
|
&::after {
|
|
488
454
|
content: '·';
|
|
@@ -492,6 +458,21 @@ function handleChooseTag(tag: string) {
|
|
|
492
458
|
}
|
|
493
459
|
}
|
|
494
460
|
}
|
|
461
|
+
.works {
|
|
462
|
+
flex: 1;
|
|
463
|
+
}
|
|
464
|
+
@media (min-width: 1440px) {
|
|
465
|
+
.works {
|
|
466
|
+
max-width: 784px;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
@media (min-width: 960px) {
|
|
471
|
+
.works {
|
|
472
|
+
max-width: 752px;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
495
476
|
.aside-container {
|
|
496
477
|
display: none;
|
|
497
478
|
flex: 1;
|
|
@@ -499,18 +480,18 @@ function handleChooseTag(tag: string) {
|
|
|
499
480
|
width: 100%;
|
|
500
481
|
max-width: 256px;
|
|
501
482
|
}
|
|
483
|
+
|
|
502
484
|
@media screen and (min-width: 960px) {
|
|
503
485
|
.aside-container {
|
|
504
486
|
display: block;
|
|
505
487
|
}
|
|
506
488
|
}
|
|
489
|
+
|
|
507
490
|
.aside-outline-container {
|
|
508
491
|
position: sticky;
|
|
509
|
-
top: calc(
|
|
510
|
-
var(--vp-nav-height) + var(--vp-layout-top-height, 0px) +
|
|
511
|
-
var(--vp-doc-top-height, 0px) + 32px
|
|
512
|
-
);
|
|
492
|
+
top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);
|
|
513
493
|
}
|
|
494
|
+
|
|
514
495
|
.lastupdate {
|
|
515
496
|
color: var(--vp-c-text-1);
|
|
516
497
|
}
|
|
@@ -522,6 +503,7 @@ function handleChooseTag(tag: string) {
|
|
|
522
503
|
display: flex;
|
|
523
504
|
flex-wrap: wrap;
|
|
524
505
|
justify-content: center;
|
|
506
|
+
|
|
525
507
|
.el-image {
|
|
526
508
|
:deep(img) {
|
|
527
509
|
object-fit: contain;
|
|
@@ -532,6 +514,7 @@ function handleChooseTag(tag: string) {
|
|
|
532
514
|
|
|
533
515
|
.swiper-mode {
|
|
534
516
|
margin-top: 16px;
|
|
517
|
+
|
|
535
518
|
.el-image {
|
|
536
519
|
:deep(img) {
|
|
537
520
|
object-fit: contain;
|
|
@@ -539,6 +522,7 @@ function handleChooseTag(tag: string) {
|
|
|
539
522
|
}
|
|
540
523
|
}
|
|
541
524
|
}
|
|
525
|
+
|
|
542
526
|
.split {
|
|
543
527
|
display: inline-block;
|
|
544
528
|
width: 1px;
|
|
@@ -186,6 +186,10 @@ export function useBlogThemeMode() {
|
|
|
186
186
|
return inject(configSymbol)!.value?.blog?.blog ?? true
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
export function useBlogInfoCollapsible() {
|
|
190
|
+
return inject(configSymbol)!.value?.blog?.home?.blogInfoCollapsible ?? false
|
|
191
|
+
}
|
|
192
|
+
|
|
189
193
|
export function useArticles() {
|
|
190
194
|
const blogConfig = useConfig()
|
|
191
195
|
const { localeIndex, site } = useData()
|
|
@@ -357,7 +361,7 @@ export function useHomeAnalysis() {
|
|
|
357
361
|
}
|
|
358
362
|
|
|
359
363
|
export function useAnalyzeTitles(wordCount: Ref<number>, readTime: ComputedRef<number>) {
|
|
360
|
-
const article =
|
|
364
|
+
const article = useArticleConfig()
|
|
361
365
|
|
|
362
366
|
const topWordCount = computed(() =>
|
|
363
367
|
replaceValue(article.value?.analyzeTitles?.topWordCount || '字数:{{value}} 个字', wordCount.value)
|
|
@@ -186,6 +186,11 @@ export namespace Theme {
|
|
|
186
186
|
* 首页数据分析卡片
|
|
187
187
|
*/
|
|
188
188
|
analysis?: HomeAnalysis
|
|
189
|
+
/**
|
|
190
|
+
* 首页博客信息卡片是否在移动端折叠展示
|
|
191
|
+
* @default false
|
|
192
|
+
*/
|
|
193
|
+
blogInfoCollapsible?: boolean
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
export interface ArticleConfig {
|
|
@@ -450,7 +455,7 @@ export namespace Theme {
|
|
|
450
455
|
|
|
451
456
|
/**
|
|
452
457
|
* oh-my-live2d 的 loadOml2d 方法的配置选项
|
|
453
|
-
* 详见 https://oml2d.
|
|
458
|
+
* 详见 https://oml2d.hacxy.cn/api/interfaces/Options.html
|
|
454
459
|
*/
|
|
455
460
|
oml2d?: Oml2dOptions
|
|
456
461
|
homeTags?: boolean | HomeTagsConfig
|
|
@@ -467,7 +472,7 @@ export namespace Theme {
|
|
|
467
472
|
imageStyle?: ImageStyleConfig
|
|
468
473
|
groupIcon?: {
|
|
469
474
|
customIcon: Record<string, string>
|
|
470
|
-
}
|
|
475
|
+
} | false
|
|
471
476
|
}
|
|
472
477
|
|
|
473
478
|
export type FormatShowDate = {
|
package/src/index.ts
CHANGED
|
@@ -35,8 +35,8 @@ import UserWorksPage from './components/UserWorks.vue'
|
|
|
35
35
|
// 内置一些特殊的主题色
|
|
36
36
|
import './styles/theme/inline-theme.var.css'
|
|
37
37
|
|
|
38
|
-
// 导入group icons
|
|
39
|
-
import 'virtual:group-icons.css'
|
|
38
|
+
// 导入group icons,改由自定义插件导入
|
|
39
|
+
// import 'virtual:group-icons.css'
|
|
40
40
|
|
|
41
41
|
export const BlogTheme: Theme = {
|
|
42
42
|
...DefaultTheme,
|
|
@@ -32,7 +32,9 @@ export function getMarkdownPlugins(cfg?: Partial<Theme.BlogConfig>) {
|
|
|
32
32
|
markdownPlugin.push(timeline)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
if (cfg?.groupIcon !== false) {
|
|
36
|
+
markdownPlugin.push(groupIconMdPlugin)
|
|
37
|
+
}
|
|
36
38
|
|
|
37
39
|
return markdownPlugin
|
|
38
40
|
}
|
package/src/utils/node/theme.ts
CHANGED
|
@@ -47,7 +47,7 @@ export async function getArticleMeta(filepath: string, route: string, timeZone =
|
|
|
47
47
|
|| getFileLastModifyTime(filepath)
|
|
48
48
|
)
|
|
49
49
|
// 无法获取时兜底当前时间
|
|
50
|
-
meta.date = formatDate(date || new Date())
|
|
50
|
+
meta.date = formatDate(date || new Date(), 'yyyy/MM/dd hh:mm:ss')
|
|
51
51
|
|
|
52
52
|
// 处理tags和categories,兼容历史文章
|
|
53
53
|
meta.categories
|
|
@@ -56,12 +56,29 @@ export function getVitePlugins(cfg: Partial<Theme.BlogConfig> = {}) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// 内置支持 group icon
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (cfg?.groupIcon !== false) {
|
|
60
|
+
plugins.push(patchGroupIconPlugin())
|
|
61
|
+
plugins.push(groupIconVitePlugin(cfg?.groupIcon))
|
|
62
|
+
}
|
|
61
63
|
|
|
62
64
|
return plugins
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
export function patchGroupIconPlugin() {
|
|
68
|
+
return {
|
|
69
|
+
name: '@sugarat/theme-plugin-patch-group-icon',
|
|
70
|
+
enforce: 'pre',
|
|
71
|
+
transform(code: string, id: string) {
|
|
72
|
+
// 匹配 theme/index.ts 或 theme/index.js 文件
|
|
73
|
+
if (id.match(/[\/\\]theme[\/\\]index\.(ts|js)$/)) {
|
|
74
|
+
// 在文件顶部插入 import 语句
|
|
75
|
+
return `import 'virtual:group-icons.css'\n${code}`
|
|
76
|
+
}
|
|
77
|
+
return code
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
65
82
|
export function registerVitePlugins(vpCfg: any, plugins: any[]) {
|
|
66
83
|
vpCfg.vite = {
|
|
67
84
|
plugins,
|