@sugarat/theme 0.1.50 → 0.2.1

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 CHANGED
@@ -119,6 +119,8 @@ declare namespace Theme {
119
119
  inspiring?: string | string[];
120
120
  inspiringTimeout?: number;
121
121
  pageSize?: number;
122
+ author?: string | boolean;
123
+ logo?: string | boolean;
122
124
  }
123
125
  interface ArticleConfig {
124
126
  readingTime?: boolean;
@@ -266,6 +268,10 @@ declare namespace Theme {
266
268
  * 启用RSS配置
267
269
  */
268
270
  RSS?: RSSOptions;
271
+ /**
272
+ * 首页页脚
273
+ */
274
+ footer?: Footer;
269
275
  }
270
276
  type RSSOptions = Omit<FeedOptions, 'id'> & {
271
277
  id?: string;
@@ -301,6 +307,40 @@ declare namespace Theme {
301
307
  limit?: number;
302
308
  ariaLabel?: string;
303
309
  };
310
+ interface Footer {
311
+ /**
312
+ * 自定义补充信息
313
+ */
314
+ message?: string;
315
+ /**
316
+ * 是否展示主题版本信息
317
+ */
318
+ version?: boolean;
319
+ /**
320
+ * copyright
321
+ */
322
+ copyright?: string | {
323
+ message: string;
324
+ link?: string;
325
+ icon?: boolean | string;
326
+ };
327
+ /**
328
+ * ICP 备案信息
329
+ */
330
+ icpRecord?: {
331
+ name: string;
332
+ link: string;
333
+ icon?: boolean | string;
334
+ };
335
+ /**
336
+ * 公安备案信息
337
+ */
338
+ securityRecord?: {
339
+ name: string;
340
+ link: string;
341
+ icon?: boolean | string;
342
+ };
343
+ }
304
344
  interface Config extends DefaultTheme.Config {
305
345
  blog?: BlogConfig;
306
346
  }
package/node.js CHANGED
@@ -32,7 +32,7 @@ __export(node_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(node_exports);
34
34
 
35
- // ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.14_vue@3.3.4/node_modules/vitepress-plugin-tabs/dist/index.js
35
+ // ../../node_modules/.pnpm/vitepress-plugin-tabs@0.2.0_vitepress@1.0.0-rc.17_vue@3.3.4/node_modules/vitepress-plugin-tabs/dist/index.js
36
36
  var tabsMarker = "=tabs";
37
37
  var tabsMarkerLen = tabsMarker.length;
38
38
  var ruleBlockTabs = (state, startLine, endLine, silent) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sugarat/theme",
3
- "version": "0.1.50",
3
+ "version": "0.2.1",
4
4
  "description": "简约风的 Vitepress 博客主题,sugarat vitepress blog theme",
5
5
  "author": "sugar",
6
6
  "license": "MIT",
@@ -53,7 +53,7 @@
53
53
  "sass": "^1.56.1",
54
54
  "tsup": " ^6.5.0",
55
55
  "typescript": "^4.8.2",
56
- "vitepress": "1.0.0-rc.14",
56
+ "vitepress": "1.0.0-rc.17",
57
57
  "vitepress-plugin-tabs": "^0.2.0",
58
58
  "vue": "^3.3.4"
59
59
  },
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts" name="BlogApp">
2
2
  import Theme from 'vitepress/theme'
3
+ import { useData } from 'vitepress'
4
+ import { computed } from 'vue'
3
5
  import { useBlogThemeMode } from '../composables/config/blog'
4
6
  import BlogHomeInfo from './BlogHomeInfo.vue'
5
7
  import BlogHomeBanner from './BlogHomeBanner.vue'
@@ -12,7 +14,10 @@ import BlogImagePreview from './BlogImagePreview.vue'
12
14
  import BlogArticleAnalyze from './BlogArticleAnalyze.vue'
13
15
  import BlogAlert from './BlogAlert.vue'
14
16
  import BlogPopover from './BlogPopover.vue'
17
+ import BlogFooter from './BlogFooter.vue'
15
18
 
19
+ const { frontmatter } = useData()
20
+ const layout = computed(() => frontmatter.value.layout)
16
21
  const isBlogTheme = useBlogThemeMode()
17
22
  const { Layout } = Theme
18
23
  </script>
@@ -20,6 +25,7 @@ const { Layout } = Theme
20
25
  <template>
21
26
  <Layout>
22
27
  <template #layout-top>
28
+ <slot name="layout-top" />
23
29
  <BlogAlert />
24
30
  <BlogPopover />
25
31
  </template>
@@ -65,7 +71,10 @@ const { Layout } = Theme
65
71
  <slot name="doc-after" />
66
72
  <BlogComment />
67
73
  </template>
68
-
74
+ <template #layout-bottom>
75
+ <BlogFooter v-if="layout === 'home'" />
76
+ <slot name="layout-bottom" />
77
+ </template>
69
78
  <!-- 透传默认主题的其它插槽 -->
70
79
  <!-- navbar -->
71
80
  <template #nav-bar-title-before>
@@ -0,0 +1,55 @@
1
+ <script setup>
2
+ import { useData } from 'vitepress'
3
+ import { computed } from 'vue'
4
+ import { useBlogConfig } from '../composables/config/blog'
5
+
6
+ const { home } = useBlogConfig()
7
+ const { frontmatter, site } = useData()
8
+ const author = computed(() =>
9
+ frontmatter.value.author
10
+ ?? frontmatter.value?.blog?.author
11
+ ?? home?.author
12
+ ?? site.value.themeConfig?.blog?.author
13
+ )
14
+ const logo = computed(() =>
15
+ frontmatter.value.logo
16
+ ?? frontmatter.value?.blog?.logo
17
+ ?? home?.logo
18
+ ?? site.value.themeConfig.logo
19
+ )
20
+ const show = computed(() => author.value || logo.value)
21
+ </script>
22
+
23
+ <template>
24
+ <div v-if="show" class="blog-author">
25
+ <img v-if="logo" :src="logo" alt="avatar">
26
+ <p v-if="author">
27
+ {{ author }}
28
+ </p>
29
+ </div>
30
+ </template>
31
+
32
+ <style scoped lang="scss">
33
+ .blog-author {
34
+ margin-bottom: 20px;
35
+
36
+ img {
37
+ display: block;
38
+ margin: 10px auto;
39
+ width: 100px;
40
+ height: 100px;
41
+ border-radius: 50%;
42
+ background-color: rgba(var(--bg-gradient-home));
43
+ }
44
+
45
+ img:hover {
46
+ transform: rotate(666turn);
47
+ transition-duration: 59s;
48
+ transition-timing-function: cubic-bezier(.34, 0, .84, 1)
49
+ }
50
+
51
+ p {
52
+ text-align: center;
53
+ }
54
+ }
55
+ </style>
@@ -0,0 +1,131 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, ref } from 'vue'
3
+ import { useHomeFooterConfig } from '../composables/config/blog'
4
+ import packageJSON from '../../package.json'
5
+ import { copyrightSVG, icpSVG, themeSVG } from '../constants/svg'
6
+
7
+ const footer = useHomeFooterConfig()
8
+ const data = ref<{
9
+ name: string
10
+ link?: string
11
+ icon?: string | boolean
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
+ })
53
+ }
54
+ })
55
+ </script>
56
+
57
+ <template>
58
+ <footer v-if="footer" class="blog-footer">
59
+ <p v-if="footer?.message" v-html="footer?.message" />
60
+ <p class="footer-item-list">
61
+ <span v-for="(item, index) in data" :key="index" class="footer-item">
62
+ <i v-if="item.icon === 'security'">
63
+ <img src="./../styles/gongan.png" alt="公网安备">
64
+ </i>
65
+ <i v-else-if="item.icon" v-html="item.icon" />
66
+ <a v-if="item.link" :href="item.link" target="_blank" rel="noopener noreferrer">
67
+ {{ item.name }}
68
+ </a>
69
+ <span v-else>{{ item.name }}</span>
70
+ </span>
71
+ </p>
72
+ </footer>
73
+ </template>
74
+
75
+ <style lang="scss" scoped>
76
+ footer.blog-footer {
77
+ text-align: center;
78
+ position: relative;
79
+ border-top: 1px solid var(--vp-c-gutter);
80
+ padding: 20px 12px;
81
+ background-color: var(--vp-c-bg);
82
+
83
+ p {
84
+ line-height: 24px;
85
+ font-size: 14px;
86
+ font-weight: 500;
87
+ color: var(--vp-c-text-2);
88
+ }
89
+ }
90
+
91
+ .footer-item-list {
92
+ display: flex;
93
+ justify-content: center;
94
+ flex-wrap: wrap;
95
+ }
96
+
97
+ @media (max-width: 719px) {
98
+ .footer-item-list {
99
+ flex-direction: column;
100
+ align-items: center;
101
+ }
102
+ }
103
+
104
+ .footer-item {
105
+ display: flex;
106
+ align-items: center;
107
+ margin: 0 8px;
108
+
109
+ i {
110
+ margin-right: 4px;
111
+ }
112
+
113
+ i :deep(svg) {
114
+ fill: var(--vp-c-text-2);
115
+ width: 16px;
116
+ height: 16px;
117
+ }
118
+
119
+ i :deep(img) {
120
+ width: 16px;
121
+ height: 16px;
122
+ }
123
+
124
+ a:hover {
125
+ color: var(--vp-c-brand-1);
126
+ text-decoration: underline;
127
+ text-decoration-color: var(--vp-c-brand-1);
128
+ text-decoration-style: dashed;
129
+ }
130
+ }
131
+ </style>
@@ -3,10 +3,14 @@ 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'
6
7
  </script>
7
8
 
8
9
  <template>
9
10
  <div class="blog-info" data-pagefind-ignore="all">
11
+ <!-- 头像信息 -->
12
+ <BlogAuthor />
13
+
10
14
  <!-- 统计数据,日后支持,点击筛选出左侧的数据 -->
11
15
  <BlogHomeOverview />
12
16
 
@@ -27,12 +27,15 @@ 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')
31
+
30
32
  export function withConfigProvider(App: Component) {
31
33
  return defineComponent({
32
34
  name: 'ConfigProvider',
33
35
  setup(_, { slots }) {
34
36
  const { theme } = useData()
35
37
  const config = computed(() => resolveConfig(theme.value))
38
+ provide(homeFooter, config.value.blog?.footer)
36
39
  provide(configSymbol, config)
37
40
  provide(
38
41
  userWorks,
@@ -197,3 +200,7 @@ export function useAutoUpdateAnchor() {
197
200
  // 返回当前锚点的响应式对象
198
201
  return currentAnchor
199
202
  }
203
+
204
+ export function useHomeFooterConfig() {
205
+ return inject(homeFooter)
206
+ }
@@ -127,6 +127,8 @@ export namespace Theme {
127
127
  inspiring?: string | string[]
128
128
  inspiringTimeout?: number
129
129
  pageSize?: number
130
+ author?: string | boolean
131
+ logo?: string | boolean
130
132
  }
131
133
 
132
134
  export interface ArticleConfig {
@@ -296,6 +298,10 @@ export namespace Theme {
296
298
  * 启用RSS配置
297
299
  */
298
300
  RSS?: RSSOptions
301
+ /**
302
+ * 首页页脚
303
+ */
304
+ footer?: Footer
299
305
  }
300
306
 
301
307
  export type RSSOptions = Omit<FeedOptions, 'id'> & {
@@ -332,6 +338,41 @@ export namespace Theme {
332
338
  limit?: number
333
339
  ariaLabel?: string
334
340
  }
341
+
342
+ export interface Footer {
343
+ /**
344
+ * 自定义补充信息
345
+ */
346
+ message?: string
347
+ /**
348
+ * 是否展示主题版本信息
349
+ */
350
+ version?: boolean
351
+ /**
352
+ * copyright
353
+ */
354
+ copyright?: string | {
355
+ message: string
356
+ link?: string
357
+ icon?: boolean | string
358
+ }
359
+ /**
360
+ * ICP 备案信息
361
+ */
362
+ icpRecord?: {
363
+ name: string
364
+ link: string
365
+ icon?: boolean | string
366
+ }
367
+ /**
368
+ * 公安备案信息
369
+ */
370
+ securityRecord?: {
371
+ name: string
372
+ link: string
373
+ icon?: boolean | string
374
+ }
375
+ }
335
376
  export interface Config extends DefaultTheme.Config {
336
377
  blog?: BlogConfig
337
378
  }
@@ -43,3 +43,12 @@ export const recommendSVG = `<svg width="512" height="512" viewBox="0 0 128 128"
43
43
  <path fill="#FFF" d="M94.8 52.5c-.4-3.8-2.1-7.3-4.9-9.7s-6.4-3.7-10-3.7c-3.7 0-7.3 1.2-10.1 3.5s-4.6 5.8-4.9 9.6c0 .3-.3.5-.5.4c-.2 0-.4-.2-.4-.5c-.1-2 .3-4.1 1.1-6c.8-1.9 2-3.6 3.5-5.1c3-2.9 7.3-4.3 11.4-4.3c4.2 0 8.3 1.6 11.3 4.5c1.5 1.5 2.7 3.2 3.5 5.1c.8 1.9 1.1 4 1 6c0 .3-.2.5-.5.5c-.3.1-.5-.1-.5-.3z"/>
44
44
  <path fill="#896024" d="M37.01 49.35c-1.03-.72-2.58-.49-3.58.95s-.67 2.97.36 3.69c1.03.72 2.58.49 3.58-.95c1.01-1.45.68-2.98-.36-3.69z"/>
45
45
  </svg>`
46
+
47
+ export const themeSVG = `<svg width="128" height="128" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
48
+ <title>主题</title>
49
+ <path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10a2.5 2.5 0 0 0 2.5-2.5c0-.61-.23-1.2-.64-1.67a.528.528 0 0 1-.13-.33c0-.28.22-.5.5-.5H16c3.31 0 6-2.69 6-6c0-4.96-4.49-9-10-9zm5.5 11c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5s1.5.67 1.5 1.5s-.67 1.5-1.5 1.5zm-3-4c-.83 0-1.5-.67-1.5-1.5S13.67 6 14.5 6s1.5.67 1.5 1.5S15.33 9 14.5 9zM5 11.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5S7.33 13 6.5 13S5 12.33 5 11.5zm6-4c0 .83-.67 1.5-1.5 1.5S8 8.33 8 7.5S8.67 6 9.5 6s1.5.67 1.5 1.5z"/>
50
+ </svg>`
51
+
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
+
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>'
Binary file