valaxy-theme-yun 0.1.2 → 0.2.2

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>
@@ -0,0 +1,14 @@
1
+ <script lang="ts" setup>
2
+ import { useConfig, useTwikoo } from 'valaxy'
3
+
4
+ const config = useConfig()
5
+ useTwikoo(config.value.comment.twikoo)
6
+ </script>
7
+
8
+ <template>
9
+ <div id="tcomment" w="full" />
10
+ </template>
11
+
12
+ <style lang="scss">
13
+ // custom twikoo style
14
+ </style>
@@ -2,9 +2,7 @@
2
2
  import { useConfig, useWaline } from 'valaxy'
3
3
 
4
4
  const config = useConfig()
5
- useWaline({
6
- serverURL: config.value.comment.waline.serverURL,
7
- })
5
+ useWaline(config.value.comment.waline)
8
6
  </script>
9
7
 
10
8
  <template>
@@ -13,7 +13,8 @@ export function useRandomData<T>(source: string | T[], random = false) {
13
13
  watch(() => source, async() => {
14
14
  let rawData: T[]
15
15
  if (typeof source === 'string') {
16
- if (!isClient) return
16
+ if (!isClient)
17
+ return
17
18
  rawData = await fetch(source).then(res => res.json()) as T[]
18
19
  }
19
20
  else { rawData = source }
package/config/index.ts CHANGED
@@ -4,9 +4,12 @@ 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
12
+ * @default '#0078E7'
10
13
  */
11
14
  primary: string
12
15
  }
@@ -99,6 +102,17 @@ export interface ThemeConfig {
99
102
  color: string
100
103
  icon: string
101
104
  }>
105
+
106
+ /**
107
+ * 菜单栏
108
+ */
109
+ menu: {
110
+ custom: {
111
+ title: string
112
+ url: string
113
+ icon: string
114
+ }
115
+ }
102
116
  }
103
117
 
104
118
  export type ThemeUserConfig = Partial<ThemeConfig>
@@ -107,6 +121,7 @@ export type ThemeUserConfig = Partial<ThemeConfig>
107
121
  * Default Config
108
122
  */
109
123
  export const defaultThemeConfig: ThemeConfig = {
124
+ safelist: ['i-ri-clipboard-line'],
110
125
  colors: {
111
126
  primary: '#0078E7',
112
127
  },
@@ -197,6 +212,39 @@ export const defaultThemeConfig: ThemeConfig = {
197
212
  icon: 'i-ri-zhihu-line',
198
213
  },
199
214
  },
215
+
216
+ menu: {
217
+ custom: {
218
+ title: 'button.about',
219
+ icon: 'i-ri-clipboard-line',
220
+ url: '/about',
221
+ },
222
+ },
200
223
  }
201
224
 
225
+ defaultThemeConfig.safelist = defaultThemeConfig.safelist.concat(generateSafelist(defaultThemeConfig))
226
+
202
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,9 +5,11 @@ 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
12
+ * @default '#0078E7'
11
13
  */
12
14
  primary: string;
13
15
  };
@@ -91,6 +93,16 @@ interface ThemeConfig {
91
93
  color: string;
92
94
  icon: string;
93
95
  }>;
96
+ /**
97
+ * 菜单栏
98
+ */
99
+ menu: {
100
+ custom: {
101
+ title: string;
102
+ url: string;
103
+ icon: string;
104
+ };
105
+ };
94
106
  }
95
107
  declare type ThemeUserConfig = Partial<ThemeConfig>;
96
108
  /**
@@ -98,6 +110,13 @@ declare type ThemeUserConfig = Partial<ThemeConfig>;
98
110
  */
99
111
  declare const defaultThemeConfig: ThemeConfig;
100
112
 
113
+ /**
114
+ * generateSafelist by config
115
+ * @param themeConfig
116
+ * @returns
117
+ */
118
+ declare function generateSafelist(themeConfig: ThemeUserConfig): string[];
119
+
101
120
  interface UserOptions {
102
121
  colors: {
103
122
  primary: string;
@@ -105,4 +124,4 @@ interface UserOptions {
105
124
  }
106
125
  declare function yunPlugin(userOptions?: Partial<ThemeConfig>): Plugin;
107
126
 
108
- 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:`$yun-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:`$yun-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};
package/index.ts CHANGED
@@ -20,7 +20,7 @@ export function yunPlugin(userOptions: Partial<ThemeConfig> = defaultThemeConfig
20
20
  css: {
21
21
  preprocessorOptions: {
22
22
  scss: {
23
- additionalData: `$yun-c-primary: ${userOptions.colors?.primary || '#0078E7'} !default;`,
23
+ additionalData: `$c-primary: ${userOptions.colors?.primary || '#0078E7'} !default;`,
24
24
  },
25
25
  },
26
26
  },
@@ -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">
@@ -32,8 +38,9 @@ const { styles, icon, color } = usePostProperty(frontmatter.value.type)
32
38
  </slot>
33
39
 
34
40
  <slot v-if="frontmatter.comment !== false" name="comment">
35
- <YunCard v-if="config.comment.waline.enable" w="full" p="4" class="comment sm:p-8 lg:px-12 xl:px-16" :class="frontmatter.nav === false ? 'mt-4' : 0">
36
- <YunWaline />
41
+ <YunCard w="full" p="4" class="comment sm:p-8 lg:px-12 xl:px-16" :class="frontmatter.nav === false ? 'mt-4' : 0">
42
+ <YunWaline v-if="config.comment.waline.enable" />
43
+ <YunTwikoo v-if="config.comment.twikoo.enable" />
37
44
  </YunCard>
38
45
  </slot>
39
46
 
@@ -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 } 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'
@@ -7,9 +7,13 @@ import { useRoute, useRouter } from 'vue-router'
7
7
  const route = useRoute()
8
8
  const router = useRouter()
9
9
 
10
+ const themeConfig = useThemeConfig()
11
+
10
12
  const { t } = useI18n()
11
13
  const frontmatter = useFrontmatter()
12
- const { tags, getTagStyle } = useTags()
14
+ const { tags, getTagStyle } = useTags({
15
+ primary: themeConfig.value.colors.primary,
16
+ })
13
17
 
14
18
  const postList = usePostList()
15
19
  const curTag = computed(() => route.query.tag as string || '')
@@ -40,13 +44,14 @@ const displayTag = (tag: string) => {
40
44
  show()
41
45
  }
42
46
 
47
+ const title = usePostTitle(frontmatter)
43
48
  </script>
44
49
 
45
50
  <template>
46
51
  <YunBase>
47
52
  <template #header>
48
53
  <YunPageHeader
49
- :title="frontmatter.title || t('menu.tags')"
54
+ :title="title || t('menu.tags')"
50
55
  :icon="frontmatter.icon || 'i-ri-tag-line'"
51
56
  :color="frontmatter.color"
52
57
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valaxy-theme-yun",
3
- "version": "0.1.2",
3
+ "version": "0.2.2",
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.1.2"
21
+ "valaxy": "0.2.2"
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
+ }