valaxy-theme-yun 0.2.0 → 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.
@@ -1,21 +1,26 @@
1
1
  <script lang="ts" setup>
2
2
  import type { Categories } from 'valaxy'
3
+ import { ref } from 'vue'
3
4
 
4
- withDefaults(defineProps<{
5
+ const props = withDefaults(defineProps<{
5
6
  categories: Categories
6
7
  /**
7
8
  * 当前层级
8
9
  */
9
10
  level?: number
10
- displayCategory: (category: string) => void
11
+ displayCategory?: (category: string) => void
12
+ collapsable?: boolean
11
13
  }>(), {
12
14
  level: 0,
15
+ collapsable: true,
13
16
  })
17
+
18
+ const collapsable = ref(props.collapsable)
14
19
  </script>
15
20
 
16
21
  <template>
17
22
  <ul v-for="category, key in Object.fromEntries(categories)" :key="key" class="category-list" m="l-4">
18
- <YunCategory :name="key.toString()" :category="category" :level="level + 1" :display-category="displayCategory" />
23
+ <YunCategory :name="key.toString()" :category="category" :level="level + 1" :display-category="displayCategory" :collapsable="collapsable" />
19
24
  </ul>
20
25
  </template>
21
26
 
@@ -1,39 +1,51 @@
1
1
  <script lang="ts" setup>
2
2
  import { ref } from 'vue'
3
- import type { Category, ParentCategory, PostCategory } from 'valaxy'
3
+ import type { Category, ParentCategory, Post, PostCategory } from 'valaxy'
4
4
  import { useI18n } from 'vue-i18n'
5
5
 
6
- defineProps<{
6
+ const props = withDefaults(defineProps<{
7
7
  name: string
8
8
  // to eliminate the warning
9
9
  category: Category
10
10
  level?: number
11
- displayCategory: (category: string) => void
12
- }>()
11
+ displayCategory?: (category: string) => void
13
12
 
14
- const showChild = ref(false)
15
- const { t } = useI18n()
13
+ /**
14
+ * collapse children
15
+ */
16
+ collapsable?: boolean
17
+ }>(), {
18
+ collapsable: true,
19
+ })
20
+
21
+ const collapsable = ref(props.collapsable)
22
+ const { t, locale } = useI18n()
23
+ const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
24
+
25
+ const getTitle = (post: Post | any) => {
26
+ return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
27
+ }
16
28
  </script>
17
29
 
18
30
  <template>
19
31
  <li v-if="category.total" class="category-list-item inline-flex items-center cursor-pointer">
20
- <span class="folder-action inline-flex" @click="showChild = !showChild">
21
- <div v-if="!showChild" i-ri-folder-add-line />
32
+ <span class="folder-action inline-flex" @click="collapsable = !collapsable">
33
+ <div v-if="collapsable" i-ri-folder-add-line />
22
34
  <div v-else style="color:var(--va-c-primary)" i-ri-folder-reduce-line /></span>
23
- <span class="category-name" m="l-1" @click="displayCategory(name)">
35
+ <span class="category-name" m="l-1" @click="displayCategory ? displayCategory(name) : null">
24
36
  {{ name === 'Uncategorized' ? t('category.uncategorized') : name }} [{{ category.total }}]
25
37
  </span>
26
38
  </li>
27
39
 
28
- <template v-if="showChild">
40
+ <template v-if="!collapsable">
29
41
  <ul v-if="(category as PostCategory).posts">
30
42
  <li v-for="post, i in (category as PostCategory).posts" :key="i" class="post-list-item" m="l-4">
31
43
  <router-link v-if="post.title" :to="post.path" class="inline-flex items-center">
32
44
  <div i-ri-file-text-line />
33
- <span m="l-1" font="serif black">{{ post.title }}</span>
45
+ <span m="l-1" font="serif black">{{ getTitle(post) }}</span>
34
46
  </router-link>
35
47
  </li>
36
48
  </ul>
37
- <YunCategories v-else :categories="(category as ParentCategory).children" :display-category="displayCategory" />
49
+ <YunCategories v-else :categories="(category as ParentCategory).children" :display-category="displayCategory" :collapsable="collapsable" />
38
50
  </template>
39
51
  </template>
@@ -2,13 +2,7 @@
2
2
  import { useI18n } from 'vue-i18n'
3
3
  import { isDark, toggleDark } from '~/composables'
4
4
 
5
- const { t, availableLocales, locale } = useI18n()
6
-
7
- const toggleLocales = () => {
8
- // change to some real logic
9
- const locales = availableLocales
10
- locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length]
11
- }
5
+ const { t } = useI18n()
12
6
  </script>
13
7
 
14
8
  <template>
@@ -17,8 +11,6 @@ const toggleLocales = () => {
17
11
  <div i="ri-sun-line dark:ri-moon-line" />
18
12
  </button>
19
13
 
20
- <button class="yun-icon-btn" :title="t('button.toggle_langs')" style="color:var(--va-c-text)" @click="toggleLocales">
21
- <div i-ri-translate class="transition transform" :class="locale === 'en' ? 'rotate-y-180' : ''" />
22
- </button>
14
+ <YunToggleLocale />
23
15
  </div>
24
16
  </template>
@@ -0,0 +1,113 @@
1
+ <script lang="ts" setup>
2
+ import { useConfig } from 'valaxy'
3
+ import { useRouter } from 'vue-router'
4
+
5
+ const config = useConfig()
6
+ const router = useRouter()
7
+ </script>
8
+
9
+ <template>
10
+ <div class="sidebar-panel">
11
+ <div class="site-info" m="t-6">
12
+ <a class="site-author-avatar" href="/about">
13
+ <img class="rounded-full" :src="config.author.avatar" alt="avatar">
14
+ <span class="site-author-status">{{ config.author.status.emoji }}</span>
15
+ </a>
16
+ <div class="site-author-name">
17
+ <a href="/about">
18
+ {{ config.author.name }}
19
+ </a>
20
+ </div>
21
+ <router-link v-if="router.hasRoute('about-site')" to="/about/site" class="site-name">
22
+ {{ config.title }}
23
+ </router-link>
24
+ <span v-else class="site-name">{{ config.title }}</span>
25
+ <h4 v-if="config.subtitle" class="site-subtitle block" text="xs">
26
+ {{ config.subtitle }}
27
+ </h4>
28
+ <div v-if="config.description" class="site-description my-1">
29
+ {{ config.description }}
30
+ </div>
31
+ </div>
32
+
33
+ <YunSidebarNav />
34
+ <hr m="t-4 b-2">
35
+ <YunSocialLinks />
36
+ <hr m="y-2">
37
+ <YunSidebarLinks />
38
+ <br>
39
+ </div>
40
+
41
+ <YunConfig />
42
+ </template>
43
+
44
+ <style lang="scss">
45
+ @use "~/styles/mixins" as *;
46
+
47
+ .sidebar-panel {
48
+ padding: 0.5rem;
49
+ }
50
+
51
+ .site-info {
52
+ &.fix-top {
53
+ margin-top: -1.5rem;
54
+ }
55
+ }
56
+
57
+ .site-author-avatar {
58
+ display: inline-block;
59
+ line-height: 0;
60
+ position: relative;
61
+
62
+ img {
63
+ height: 96px;
64
+ width: 96px;
65
+ max-width: 100%;
66
+ margin: 0px;
67
+ padding: 4px;
68
+ background-color: white;
69
+ box-shadow: 0 0 10px rgba(black, 0.2);
70
+ transition: 0.4s;
71
+
72
+ &:hover {
73
+ box-shadow: 0 0 30px rgba(var(--va-c-primary-rgb), 0.2);
74
+ }
75
+ }
76
+ }
77
+
78
+ .site-author-name {
79
+ margin-top: 0;
80
+ margin-bottom: 1rem;
81
+ line-height: 1.5;
82
+ }
83
+
84
+ .site-author-status {
85
+ position: absolute;
86
+ height: 1.8rem;
87
+ width: 1.8rem;
88
+ bottom: 0;
89
+ right: 0;
90
+ line-height: 1.8rem;
91
+ border-radius: 50%;
92
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
93
+ background-color: var(--va-c-bg-light);
94
+
95
+ border: 1px solid rgba(255, 255, 255, 0.1);
96
+ }
97
+
98
+ .site-name {
99
+ color: var(--va-c-text);
100
+ font-family: get-css-var('font-serif');
101
+ font-weight: get-css-var('font-serif-weight');
102
+ }
103
+
104
+ .site-subtitle {
105
+ color: get-css-var('c-gray');
106
+ display: block;
107
+ }
108
+
109
+ .site-description {
110
+ color: var(--va-c-text);
111
+ font-size: 0.8rem;
112
+ }
113
+ </style>
@@ -11,6 +11,13 @@ defineProps<{
11
11
  </script>
12
12
 
13
13
  <template>
14
+ <div v-if="frontmatter.draft" class="post-draft-icon" title="draft">
15
+ <div i-ri-draft-line />
16
+ </div>
17
+ <div v-if="frontmatter.top" class="post-top-icon">
18
+ <div i-ri-pushpin-line />
19
+ </div>
20
+
14
21
  <div v-if="frontmatter" class="post-meta justify-center" flex="~" text="sm">
15
22
  <div v-if="frontmatter.date" class="post-time flex items-center">
16
23
  <div class="inline-block" i-ri-calendar-line />
@@ -25,5 +32,20 @@ defineProps<{
25
32
  </div>
26
33
  </template>
27
34
 
28
- <style lang="scss">
35
+ <style>
36
+ .post-draft-icon {
37
+ position: absolute;
38
+ top: 1rem;
39
+ left: 1rem;
40
+ color: var(--va-c-gray);
41
+ font-size: 1.2rem;
42
+ }
43
+
44
+ .post-top-icon {
45
+ position: absolute;
46
+ top: 1rem;
47
+ right: 1rem;
48
+ color: var(--va-c-warning);
49
+ font-size: 1.2rem;
50
+ }
29
51
  </style>
@@ -1,111 +1,39 @@
1
1
  <script lang="ts" setup>
2
- import { useConfig } from 'valaxy'
3
- import { useRouter } from 'vue-router'
4
-
5
- const config = useConfig()
6
- const router = useRouter()
2
+ import { ref } from 'vue'
3
+ const showOverview = ref(false)
7
4
  </script>
8
5
 
9
6
  <template>
10
- <div class="sidebar-panel">
11
- <div class="site-info" m="t-6">
12
- <a class="site-author-avatar" href="/about">
13
- <img class="rounded-full" :src="config.author.avatar" alt="avatar">
14
- <span class="site-author-status">{{ config.author.status.emoji }}</span>
15
- </a>
16
- <div class="site-author-name">
17
- <a href="/about">
18
- {{ config.author.name }}
19
- </a>
20
- </div>
21
- <router-link v-if="router.hasRoute('about-site')" to="/about/site" class="site-name">
22
- {{ config.title }}
23
- </router-link>
24
- <span v-else class="site-name">{{ config.title }}</span>
25
- <h4 v-if="config.subtitle" class="site-subtitle block" text="xs">
26
- {{ config.subtitle }}
27
- </h4>
28
- <div v-if="config.description" class="site-description my-1">
29
- {{ config.description }}
30
- </div>
31
- </div>
7
+ <div v-if="$slots.default" class="sidebar-nav" m="t-6">
8
+ <button m="x-4" class="sidebar-nav-item yun-icon-btn" :class="showOverview && 'active'" @click="showOverview = true">
9
+ <div i-ri-passport-line />
10
+ </button>
11
+ <button m="x-4" class="sidebar-nav-item yun-icon-btn" :class="!showOverview && 'active'" @click="showOverview = false">
12
+ <div i-ri-list-ordered />
13
+ </button>
14
+ </div>
15
+
16
+ <div v-if="showOverview || !$slots.default" :class="$slots.default && '-mt-4'">
17
+ <YunOverview />
18
+ </div>
32
19
 
33
- <YunSidebarNav />
34
- <hr m="t-4 b-2">
35
- <YunSocialLinks />
36
- <hr m="y-2">
37
- <YunSidebarLinks />
38
- <br>
20
+ <div v-else>
21
+ <slot />
39
22
  </div>
40
23
  </template>
41
24
 
42
25
  <style lang="scss">
43
- @use "~/styles/mixins" as *;
26
+ .sidebar-nav {
27
+ .sidebar-nav-item {
28
+ color: var(--va-c-primary);
29
+ border: 1px solid var(--va-c-primary);
44
30
 
45
- .sidebar-panel {
46
- padding: 0.5rem;
47
- }
31
+ &.active {
32
+ border: 1px solid var(--va-c-primary);
48
33
 
49
- .site-info {
50
- &.fix-top {
51
- margin-top: -1.5rem;
52
- }
53
- }
54
-
55
- .site-author-avatar {
56
- display: inline-block;
57
- line-height: 0;
58
- position: relative;
59
-
60
- img {
61
- height: 96px;
62
- width: 96px;
63
- max-width: 100%;
64
- margin: 0px;
65
- padding: 4px;
66
- background-color: white;
67
- box-shadow: 0 0 10px rgba(black, 0.2);
68
- transition: 0.4s;
69
-
70
- &:hover {
71
- box-shadow: 0 0 30px rgba(var(--va-c-primary-rgb), 0.2);
34
+ color: white;
35
+ background-color: var(--va-c-primary);
72
36
  }
73
37
  }
74
38
  }
75
-
76
- .site-author-name {
77
- margin-top: 0;
78
- margin-bottom: 1rem;
79
- line-height: 1.5;
80
- }
81
-
82
- .site-author-status {
83
- position: absolute;
84
- height: 1.8rem;
85
- width: 1.8rem;
86
- bottom: 0;
87
- right: 0;
88
- line-height: 1.8rem;
89
- border-radius: 50%;
90
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
91
- background-color: var(--va-c-bg-light);
92
-
93
- border: 1px solid rgba(255, 255, 255, 0.1);
94
- }
95
-
96
- .site-name {
97
- color: var(--va-c-text);
98
- font-family: get-css-var('font-serif');
99
- font-weight: get-css-var('font-serif-weight');
100
- }
101
-
102
- .site-subtitle {
103
- color: get-css-var('c-gray');
104
- display: block;
105
- }
106
-
107
- .site-description {
108
- color: var(--va-c-text);
109
- font-size: 0.8rem;
110
- }
111
39
  </style>
@@ -1,9 +1,10 @@
1
1
  <script lang="ts" setup>
2
- import { useCategory, usePostList, useTag } from 'valaxy'
2
+ import { useCategory, usePostList, useTag, useThemeConfig } from 'valaxy'
3
3
  import { useI18n } from 'vue-i18n'
4
4
 
5
5
  const { t } = useI18n()
6
6
 
7
+ const themeConfig = useThemeConfig()
7
8
  const posts = usePostList()
8
9
  const categories = useCategory()
9
10
  const tags = useTag()
@@ -28,8 +29,8 @@ const tags = useTag()
28
29
  <span class="count">{{ Array.from(tags).length }}</span>
29
30
  </router-link>
30
31
 
31
- <router-link class="site-link-item yun-icon-btn" to="/about" :title="t('button.about')">
32
- <div i-ri-clipboard-line />
32
+ <router-link class="site-link-item yun-icon-btn" :to="themeConfig.menu.custom.url" :title="t(themeConfig.menu.custom.title)">
33
+ <div :class="themeConfig.menu.custom.icon" />
33
34
  </router-link>
34
35
  </nav>
35
36
  </template>
@@ -11,9 +11,6 @@ const showQr = ref(false)
11
11
 
12
12
  <template>
13
13
  <div class="yun-sponsor-container flex justify-center items-center flex-col">
14
- <!-- <a href="" :title="t('reward.donate')">
15
-
16
- </a> -->
17
14
  <button class="sponsor-button yun-icon-btn shadow hover:shadow-md" :title="t('reward.donate')" text="red-400" @click="showQr = !showQr">
18
15
  <div i-ri-heart-line />
19
16
  </button>
@@ -26,7 +23,7 @@ const showQr = ref(false)
26
23
  :href="method.url" target="_blank"
27
24
  :style="`color:${method.color}`"
28
25
  >
29
- <img w="full" class="sponsor-method-img" border="~ rounded" p="1" loading="lazy" :src="method.url" :title="method.name">
26
+ <img class="sponsor-method-img" border="~ rounded" p="1" loading="lazy" :src="method.url" :title="method.name">
30
27
  <div text="xl" m="2" :class="method.icon" />
31
28
  </a>
32
29
  </div>
@@ -0,0 +1,25 @@
1
+ <script lang="ts" setup>
2
+ import { isClient, useStorage } from '@vueuse/core'
3
+ import { useI18n } from 'vue-i18n'
4
+ const { t, availableLocales, locale } = useI18n()
5
+
6
+ const lang = useStorage('valaxy-locale', locale.value)
7
+
8
+ const toggleLocales = () => {
9
+ // change to some real logic
10
+ const locales = availableLocales
11
+
12
+ locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length]
13
+ // for localStorage
14
+ lang.value = locale.value
15
+
16
+ if (isClient)
17
+ document.documentElement.setAttribute('lang', locale.value)
18
+ }
19
+ </script>
20
+
21
+ <template>
22
+ <button class="yun-icon-btn" :title="t('button.toggle_langs')" style="color:var(--va-c-text)" @click="toggleLocales">
23
+ <div i-ri-translate class="transition transform" :class="locale === 'en' ? 'rotate-y-180' : ''" />
24
+ </button>
25
+ </template>
package/config/index.ts CHANGED
@@ -4,6 +4,8 @@ export const anonymousImage = 'https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/ava
4
4
  * Theme Config
5
5
  */
6
6
  export interface ThemeConfig {
7
+ // for unocss
8
+ safelist: string[]
7
9
  colors: {
8
10
  /**
9
11
  * primary color
@@ -100,6 +102,17 @@ export interface ThemeConfig {
100
102
  color: string
101
103
  icon: string
102
104
  }>
105
+
106
+ /**
107
+ * 菜单栏
108
+ */
109
+ menu: {
110
+ custom: {
111
+ title: string
112
+ url: string
113
+ icon: string
114
+ }
115
+ }
103
116
  }
104
117
 
105
118
  export type ThemeUserConfig = Partial<ThemeConfig>
@@ -108,6 +121,7 @@ export type ThemeUserConfig = Partial<ThemeConfig>
108
121
  * Default Config
109
122
  */
110
123
  export const defaultThemeConfig: ThemeConfig = {
124
+ safelist: ['i-ri-clipboard-line'],
111
125
  colors: {
112
126
  primary: '#0078E7',
113
127
  },
@@ -198,6 +212,39 @@ export const defaultThemeConfig: ThemeConfig = {
198
212
  icon: 'i-ri-zhihu-line',
199
213
  },
200
214
  },
215
+
216
+ menu: {
217
+ custom: {
218
+ title: 'button.about',
219
+ icon: 'i-ri-clipboard-line',
220
+ url: '/about',
221
+ },
222
+ },
201
223
  }
202
224
 
225
+ defaultThemeConfig.safelist = defaultThemeConfig.safelist.concat(generateSafelist(defaultThemeConfig))
226
+
203
227
  export default defaultThemeConfig
228
+
229
+ /**
230
+ * generateSafelist by config
231
+ * @param themeConfig
232
+ * @returns
233
+ */
234
+ export function generateSafelist(themeConfig: ThemeUserConfig) {
235
+ const safelist = []
236
+
237
+ const types = themeConfig.types
238
+ if (types) {
239
+ for (const type in types)
240
+ safelist.push(types[type].icon)
241
+ }
242
+
243
+ if (themeConfig.footer?.icon?.name)
244
+ safelist.push(themeConfig.footer?.icon?.name)
245
+
246
+ if (themeConfig.menu?.custom?.icon)
247
+ safelist.push(themeConfig.menu?.custom?.icon)
248
+
249
+ return safelist
250
+ }
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ declare const anonymousImage = "https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/av
5
5
  * Theme Config
6
6
  */
7
7
  interface ThemeConfig {
8
+ safelist: string[];
8
9
  colors: {
9
10
  /**
10
11
  * primary color
@@ -92,6 +93,16 @@ interface ThemeConfig {
92
93
  color: string;
93
94
  icon: string;
94
95
  }>;
96
+ /**
97
+ * 菜单栏
98
+ */
99
+ menu: {
100
+ custom: {
101
+ title: string;
102
+ url: string;
103
+ icon: string;
104
+ };
105
+ };
95
106
  }
96
107
  declare type ThemeUserConfig = Partial<ThemeConfig>;
97
108
  /**
@@ -99,6 +110,13 @@ declare type ThemeUserConfig = Partial<ThemeConfig>;
99
110
  */
100
111
  declare const defaultThemeConfig: ThemeConfig;
101
112
 
113
+ /**
114
+ * generateSafelist by config
115
+ * @param themeConfig
116
+ * @returns
117
+ */
118
+ declare function generateSafelist(themeConfig: ThemeUserConfig): string[];
119
+
102
120
  interface UserOptions {
103
121
  colors: {
104
122
  primary: string;
@@ -106,4 +124,4 @@ interface UserOptions {
106
124
  }
107
125
  declare function yunPlugin(userOptions?: Partial<ThemeConfig>): Plugin;
108
126
 
109
- export { ThemeConfig, ThemeUserConfig, UserOptions, anonymousImage, yunPlugin as default, defaultThemeConfig, yunPlugin };
127
+ export { ThemeConfig, ThemeUserConfig, UserOptions, anonymousImage, yunPlugin as default, defaultThemeConfig, generateSafelist, yunPlugin };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var t="https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg",e= exports.defaultThemeConfig ={colors:{primary:"#0078E7"},banner:{enable:!0,title:"\u4E91\u6E38\u541B\u7684\u5C0F\u7AD9"},bg_image:{enable:!0,url:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/stars-timing-0-blur-30px.jpg",dark:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/galaxy.jpg",opacity:1},say:{enable:!0,api:"https://el-bot-api.vercel.app/api/words/young",hitokoto:{enable:!1,api:"https://v1.hitokoto.cn"}},pages:[],footer:{since:2022,icon:{name:"i-ri-cloud-line",animated:!0,color:"var(--va-c-primary)",url:"https://sponsors.yunyoujun.cn",title:"Sponsor YunYouJun"},powered:!0,beian:{enable:!1,icp:""}},types:{link:{color:"var(--va-c-primary)",icon:"i-ri-external-link-line"},bilibili:{color:"#FF8EB3",icon:"i-ri-bilibili-line"},douban:{color:"#007722",icon:"i-ri-douban-line"},github:{color:"var(--va-c-text)",icon:"i-ri-github-line"},"netease-cloud-music":{color:"#C10D0C",icon:"i-ri-netease-cloud-music-line"},notion:{color:"var(--va-c-text)",icon:"i-simple-icons-notion"},twitter:{color:"#1da1f2",icon:"i-ri-twitter-line"},wechat:{color:"#1AAD19",icon:"i-ri-wechat-2-line"},weibo:{color:"#E6162D",icon:"i-ri-weibo-line"},yuque:{color:"#25b864",icon:"i-ant-design-yuque-outlined"},zhihu:{color:"#0084FF",icon:"i-ri-zhihu-line"}}};function r(n=e){return{name:"valaxy-theme-yun",enforce:"pre",config(){var i;return{css:{preprocessorOptions:{scss:{additionalData:`$c-primary: ${((i=n.colors)==null?void 0:i.primary)||"#0078E7"} !default;`}}}}}}}var c=r;exports.anonymousImage = t; exports.default = c; exports.defaultThemeConfig = e; exports.yunPlugin = r;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var d="https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg",n= exports.defaultThemeConfig ={safelist:["i-ri-clipboard-line"],colors:{primary:"#0078E7"},banner:{enable:!0,title:"\u4E91\u6E38\u541B\u7684\u5C0F\u7AD9"},bg_image:{enable:!0,url:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/stars-timing-0-blur-30px.jpg",dark:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/galaxy.jpg",opacity:1},say:{enable:!0,api:"https://el-bot-api.vercel.app/api/words/young",hitokoto:{enable:!1,api:"https://v1.hitokoto.cn"}},pages:[],footer:{since:2022,icon:{name:"i-ri-cloud-line",animated:!0,color:"var(--va-c-primary)",url:"https://sponsors.yunyoujun.cn",title:"Sponsor YunYouJun"},powered:!0,beian:{enable:!1,icp:""}},types:{link:{color:"var(--va-c-primary)",icon:"i-ri-external-link-line"},bilibili:{color:"#FF8EB3",icon:"i-ri-bilibili-line"},douban:{color:"#007722",icon:"i-ri-douban-line"},github:{color:"var(--va-c-text)",icon:"i-ri-github-line"},"netease-cloud-music":{color:"#C10D0C",icon:"i-ri-netease-cloud-music-line"},notion:{color:"var(--va-c-text)",icon:"i-simple-icons-notion"},twitter:{color:"#1da1f2",icon:"i-ri-twitter-line"},wechat:{color:"#1AAD19",icon:"i-ri-wechat-2-line"},weibo:{color:"#E6162D",icon:"i-ri-weibo-line"},yuque:{color:"#25b864",icon:"i-ant-design-yuque-outlined"},zhihu:{color:"#0084FF",icon:"i-ri-zhihu-line"}},menu:{custom:{title:"button.about",icon:"i-ri-clipboard-line",url:"/about"}}};n.safelist=n.safelist.concat(b(n));function b(i){var t,r,a,l,s,c,u,p;let e=[],o=i.types;if(o)for(let g in o)e.push(o[g].icon);return(r=(t=i.footer)==null?void 0:t.icon)!=null&&r.name&&e.push((l=(a=i.footer)==null?void 0:a.icon)==null?void 0:l.name),(c=(s=i.menu)==null?void 0:s.custom)!=null&&c.icon&&e.push((p=(u=i.menu)==null?void 0:u.custom)==null?void 0:p.icon),e}function f(i=n){return{name:"valaxy-theme-yun",enforce:"pre",config(){var e;return{css:{preprocessorOptions:{scss:{additionalData:`$c-primary: ${((e=i.colors)==null?void 0:e.primary)||"#0078E7"} !default;`}}}}}}}var v=f;exports.anonymousImage = d; exports.default = v; exports.defaultThemeConfig = n; exports.generateSafelist = b; exports.yunPlugin = f;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var a="https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg",e={colors:{primary:"#0078E7"},banner:{enable:!0,title:"\u4E91\u6E38\u541B\u7684\u5C0F\u7AD9"},bg_image:{enable:!0,url:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/stars-timing-0-blur-30px.jpg",dark:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/galaxy.jpg",opacity:1},say:{enable:!0,api:"https://el-bot-api.vercel.app/api/words/young",hitokoto:{enable:!1,api:"https://v1.hitokoto.cn"}},pages:[],footer:{since:2022,icon:{name:"i-ri-cloud-line",animated:!0,color:"var(--va-c-primary)",url:"https://sponsors.yunyoujun.cn",title:"Sponsor YunYouJun"},powered:!0,beian:{enable:!1,icp:""}},types:{link:{color:"var(--va-c-primary)",icon:"i-ri-external-link-line"},bilibili:{color:"#FF8EB3",icon:"i-ri-bilibili-line"},douban:{color:"#007722",icon:"i-ri-douban-line"},github:{color:"var(--va-c-text)",icon:"i-ri-github-line"},"netease-cloud-music":{color:"#C10D0C",icon:"i-ri-netease-cloud-music-line"},notion:{color:"var(--va-c-text)",icon:"i-simple-icons-notion"},twitter:{color:"#1da1f2",icon:"i-ri-twitter-line"},wechat:{color:"#1AAD19",icon:"i-ri-wechat-2-line"},weibo:{color:"#E6162D",icon:"i-ri-weibo-line"},yuque:{color:"#25b864",icon:"i-ant-design-yuque-outlined"},zhihu:{color:"#0084FF",icon:"i-ri-zhihu-line"}}};function t(n=e){return{name:"valaxy-theme-yun",enforce:"pre",config(){var i;return{css:{preprocessorOptions:{scss:{additionalData:`$c-primary: ${((i=n.colors)==null?void 0:i.primary)||"#0078E7"} !default;`}}}}}}}var s=t;export{a as anonymousImage,s as default,e as defaultThemeConfig,t as yunPlugin};
1
+ var h="https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg",n={safelist:["i-ri-clipboard-line"],colors:{primary:"#0078E7"},banner:{enable:!0,title:"\u4E91\u6E38\u541B\u7684\u5C0F\u7AD9"},bg_image:{enable:!0,url:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/stars-timing-0-blur-30px.jpg",dark:"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/bg/galaxy.jpg",opacity:1},say:{enable:!0,api:"https://el-bot-api.vercel.app/api/words/young",hitokoto:{enable:!1,api:"https://v1.hitokoto.cn"}},pages:[],footer:{since:2022,icon:{name:"i-ri-cloud-line",animated:!0,color:"var(--va-c-primary)",url:"https://sponsors.yunyoujun.cn",title:"Sponsor YunYouJun"},powered:!0,beian:{enable:!1,icp:""}},types:{link:{color:"var(--va-c-primary)",icon:"i-ri-external-link-line"},bilibili:{color:"#FF8EB3",icon:"i-ri-bilibili-line"},douban:{color:"#007722",icon:"i-ri-douban-line"},github:{color:"var(--va-c-text)",icon:"i-ri-github-line"},"netease-cloud-music":{color:"#C10D0C",icon:"i-ri-netease-cloud-music-line"},notion:{color:"var(--va-c-text)",icon:"i-simple-icons-notion"},twitter:{color:"#1da1f2",icon:"i-ri-twitter-line"},wechat:{color:"#1AAD19",icon:"i-ri-wechat-2-line"},weibo:{color:"#E6162D",icon:"i-ri-weibo-line"},yuque:{color:"#25b864",icon:"i-ant-design-yuque-outlined"},zhihu:{color:"#0084FF",icon:"i-ri-zhihu-line"}},menu:{custom:{title:"button.about",icon:"i-ri-clipboard-line",url:"/about"}}};n.safelist=n.safelist.concat(f(n));function f(i){var t,r,a,l,s,c,u,p;let e=[],o=i.types;if(o)for(let g in o)e.push(o[g].icon);return(r=(t=i.footer)==null?void 0:t.icon)!=null&&r.name&&e.push((l=(a=i.footer)==null?void 0:a.icon)==null?void 0:l.name),(c=(s=i.menu)==null?void 0:s.custom)!=null&&c.icon&&e.push((p=(u=i.menu)==null?void 0:u.custom)==null?void 0:p.icon),e}function d(i=n){return{name:"valaxy-theme-yun",enforce:"pre",config(){var e;return{css:{preprocessorOptions:{scss:{additionalData:`$c-primary: ${((e=i.colors)==null?void 0:e.primary)||"#0078E7"} !default;`}}}}}}}var x=d;export{h as anonymousImage,x as default,n as defaultThemeConfig,f as generateSafelist,d as yunPlugin};
@@ -1,17 +1,19 @@
1
1
  <script lang="ts" setup>
2
- import { useFrontmatter, usePostList } from 'valaxy'
2
+ import { useFrontmatter, usePostList, usePostTitle } from 'valaxy'
3
3
  import { useI18n } from 'vue-i18n'
4
4
 
5
5
  const { t } = useI18n()
6
6
 
7
7
  const frontmatter = useFrontmatter()
8
8
  const postList = usePostList()
9
+
10
+ const title = usePostTitle(frontmatter)
9
11
  </script>
10
12
 
11
13
  <template>
12
14
  <YunBase>
13
15
  <template #header>
14
- <YunPageHeader :title="frontmatter.title || t('menu.archives')" :icon="frontmatter.icon || 'i-ri-archive-line'" :color="frontmatter.color" />
16
+ <YunPageHeader :title="title || t('menu.archives')" :icon="frontmatter.icon || 'i-ri-archive-line'" :color="frontmatter.color" />
15
17
  </template>
16
18
  <template #content>
17
19
  <router-view />
package/layouts/base.vue CHANGED
@@ -1,22 +1,28 @@
1
1
  <script lang="ts" setup>
2
- import { useConfig, useFrontmatter, usePostProperty } from 'valaxy'
2
+ import { useConfig, useFrontmatter, usePostProperty, usePostTitle } from 'valaxy'
3
3
  const frontmatter = useFrontmatter()
4
4
 
5
5
  const config = useConfig()
6
6
 
7
7
  const { styles, icon, color } = usePostProperty(frontmatter.value.type)
8
+ const title = usePostTitle(frontmatter)
8
9
  </script>
9
10
 
10
11
  <template>
11
12
  <ValaxySidebar>
12
- <slot name="sidebar" />
13
+ <slot name="sidebar">
14
+ <YunSidebar v-if="$slots['sidebar-child']">
15
+ <slot name="sidebar-child" />
16
+ </YunSidebar>
17
+ <YunSidebar v-else />
18
+ </slot>
13
19
  </ValaxySidebar>
14
20
 
15
21
  <main class="yun-main flex lt-md:ml-0">
16
22
  <div flex="~ 1 col" w="full" p="l-4 lt-md:0">
17
- <YunCard m="0" p="4" class="page-card sm:p-6 lg:px-12 xl:px-16" :style="styles">
23
+ <YunCard m="0" p="4" class="relative page-card sm:p-6 lg:px-12 xl:px-16" :style="styles">
18
24
  <slot name="header">
19
- <YunPageHeader :title="frontmatter.title" :icon="frontmatter.icon || icon" :color="frontmatter.color || color" />
25
+ <YunPageHeader :title="title" :icon="frontmatter.icon || icon" :color="frontmatter.color || color" />
20
26
  </slot>
21
27
  <template #content>
22
28
  <slot name="content">
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { computed, ref } from 'vue'
3
- import { useCategory, useFrontmatter, useInvisibleElement, usePostList } from 'valaxy'
3
+ import { useCategory, useFrontmatter, useInvisibleElement, usePostList, usePostTitle } from 'valaxy'
4
4
  import { useI18n } from 'vue-i18n'
5
5
  import { useRoute, useRouter } from 'vue-router'
6
6
 
@@ -39,13 +39,15 @@ const displayCategory = (category: string) => {
39
39
 
40
40
  show()
41
41
  }
42
+
43
+ const title = usePostTitle(frontmatter)
42
44
  </script>
43
45
 
44
46
  <template>
45
47
  <YunBase>
46
48
  <template #header>
47
49
  <YunPageHeader
48
- :title="frontmatter.title || t('menu.categories')"
50
+ :title="title || t('menu.categories')"
49
51
  :icon="frontmatter.icon || 'i-ri-folder-2-line'"
50
52
  :color="frontmatter.color"
51
53
  />
package/layouts/home.vue CHANGED
@@ -12,7 +12,12 @@ const isHome = useLayout('home')
12
12
 
13
13
  <template>
14
14
  <main class="yun-main justify-center items-center" :class="(isHome && !app.isSidebarOpen) && 'pl-0'" flex="~ col" w="full">
15
- <ValaxySidebar />
15
+ <ValaxySidebar>
16
+ <slot name="sidebar">
17
+ <YunSidebar />
18
+ </slot>
19
+ </ValaxySidebar>
20
+
16
21
  <YunBanner />
17
22
  <YunSay w="full" />
18
23
 
package/layouts/post.vue CHANGED
@@ -13,9 +13,11 @@ const url = useFullUrl()
13
13
  <slot name="header">
14
14
  <YunPostMeta :frontmatter="frontmatter" />
15
15
  </slot>
16
- <Transition appear>
17
- <router-view />
18
- </Transition>
16
+ <router-view v-slot="{Component}">
17
+ <Transition appear>
18
+ <component :is="Component" />
19
+ </Transition>
20
+ </router-view>
19
21
  <YunSponsor v-if="frontmatter.sponsor || config.sponsor.enable" />
20
22
  <ValaxyCopyright v-if="frontmatter.copyright || config.license.enabled" :url="url" m="y-4" />
21
23
  </main>
package/layouts/tags.vue CHANGED
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { useFrontmatter, useInvisibleElement, usePostList, useTags, useThemeConfig } from 'valaxy'
2
+ import { useFrontmatter, useInvisibleElement, usePostList, usePostTitle, useTags, useThemeConfig } from 'valaxy'
3
3
  import { useI18n } from 'vue-i18n'
4
4
  import { computed, ref } from 'vue'
5
5
  import { useRoute, useRouter } from 'vue-router'
@@ -44,13 +44,14 @@ const displayTag = (tag: string) => {
44
44
  show()
45
45
  }
46
46
 
47
+ const title = usePostTitle(frontmatter)
47
48
  </script>
48
49
 
49
50
  <template>
50
51
  <YunBase>
51
52
  <template #header>
52
53
  <YunPageHeader
53
- :title="frontmatter.title || t('menu.tags')"
54
+ :title="title || t('menu.tags')"
54
55
  :icon="frontmatter.icon || 'i-ri-tag-line'"
55
56
  :color="frontmatter.color"
56
57
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valaxy-theme-yun",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -18,7 +18,7 @@
18
18
  "url": "https://www.yunyoujun.cn"
19
19
  },
20
20
  "devDependencies": {
21
- "valaxy": "0.2.0"
21
+ "valaxy": "0.2.1"
22
22
  },
23
23
  "scripts": {
24
24
  "build": "tsup",
@@ -1,11 +1,10 @@
1
- @use '~/styles/mixins' as *;
1
+ @use "~/styles/mixins" as *;
2
2
 
3
3
  .post-card {
4
4
  position: relative;
5
5
  max-width: var(--yun-post-card-max-width);
6
6
  }
7
7
 
8
-
9
8
  .post-title {
10
9
  display: flex;
11
10
  justify-content: center;
@@ -28,8 +27,9 @@
28
27
  margin-right: 0.4rem;
29
28
  }
30
29
 
31
- &::before, &::after {
32
- content: '';
30
+ &::before,
31
+ &::after {
32
+ content: "";
33
33
  position: absolute;
34
34
  width: 10px;
35
35
  height: 10px;
@@ -53,20 +53,13 @@
53
53
  transform: translate3d(-10px, -10px, 0);
54
54
  }
55
55
 
56
- &:hover::before, &:hover::after {
56
+ &:hover::before,
57
+ &:hover::after {
57
58
  opacity: 1;
58
59
  transform: translate3d(0, 0, 0);
59
60
  }
60
61
  }
61
62
 
62
- .post-top-icon {
63
- position: absolute;
64
- top: 1rem;
65
- right: 1rem;
66
- color: var(--va-c-warning);
67
- font-size: 1.2rem;
68
- }
69
-
70
63
  .post-link-btn,
71
64
  .markdown-body .post-link-btn {
72
65
  background-color: var(--card-c-primary);
@@ -9,3 +9,21 @@ html.dark {
9
9
  --c-toc-link: var(--va-c-text-dark);
10
10
  }
11
11
  }
12
+
13
+ .markdown-body {
14
+ h1,
15
+ h2,
16
+ h3,
17
+ h4,
18
+ h5,
19
+ h6 {
20
+ font-family: var(--va-font-serif);
21
+ font-weight: 900;
22
+ }
23
+
24
+ ul {
25
+ li > p {
26
+ margin-bottom: 0;
27
+ }
28
+ }
29
+ }