valaxy 0.18.10 → 0.19.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.
- package/client/App.vue +6 -11
- package/client/components/builtin/ValaxyMermaid.vue +4 -3
- package/client/composables/aside.ts +12 -5
- package/client/composables/categories.ts +12 -1
- package/client/composables/dark.ts +77 -38
- package/client/composables/layout.ts +10 -2
- package/client/composables/outline/headers.ts +12 -1
- package/client/composables/sidebar.ts +41 -2
- package/client/composables/tags.ts +9 -0
- package/client/locales/en.yml +2 -2
- package/client/locales/zh-CN.yml +1 -1
- package/client/main.ts +12 -10
- package/client/setup/main.ts +0 -2
- package/client/setup/mermaid.ts +7 -0
- package/client/setups.ts +15 -0
- package/client/shims.d.ts +3 -0
- package/client/stores/app.ts +20 -4
- package/client/styles/css/css-vars.css +19 -0
- package/client/styles/{global/index.scss → css/main.css} +1 -1
- package/client/styles/css-vars.scss +1 -1
- package/client/styles/index.scss +0 -1
- package/client/styles/palette.scss +0 -18
- package/client/types/index.ts +3 -0
- package/client/utils/router.ts +18 -0
- package/client/utils/time.ts +8 -0
- package/dist/chunk-PTYUKZAG.mjs +157 -0
- package/dist/chunk-RVKKZQ6C.cjs +156 -0
- package/dist/{config-D40lUB2J.d.cts → config-BuLv3zWm.d.cts} +40 -7
- package/dist/{config-D40lUB2J.d.ts → config-BuLv3zWm.d.ts} +40 -7
- package/dist/node/cli/index.cjs +1 -1
- package/dist/node/cli/index.mjs +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +3 -2
- package/dist/node/index.d.ts +3 -2
- package/dist/node/index.mjs +1 -1
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +3 -2
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.mjs +1 -1
- package/package.json +14 -13
- package/types/config.ts +4 -7
- package/types/default-theme.ts +38 -0
- package/dist/chunk-57MNPFIN.mjs +0 -150
- package/dist/chunk-KIFZXMGL.cjs +0 -149
- /package/dist/{chunk-OE2XGI4S.mjs → chunk-7VTZAWDO.mjs} +0 -0
- /package/dist/{chunk-EKEE6AAY.cjs → chunk-I6UPHJXQ.cjs} +0 -0
package/client/App.vue
CHANGED
|
@@ -16,14 +16,13 @@ import { definePerson, defineWebPage, defineWebSite, useSchemaOrg } from '@unhea
|
|
|
16
16
|
// they will be rendered correctly in the html results with vite-ssg
|
|
17
17
|
import { useSiteConfig } from './config'
|
|
18
18
|
import ValaxyAddons from './components/ValaxyAddons.vue'
|
|
19
|
-
import {
|
|
19
|
+
import { useFrontmatter } from './composables'
|
|
20
20
|
|
|
21
21
|
// <link rel="apple-touch-icon" href="/pwa-192x192.png">
|
|
22
22
|
// <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
|
|
23
23
|
|
|
24
24
|
const siteConfig = useSiteConfig()
|
|
25
25
|
// todo, allow user config
|
|
26
|
-
const themeColor = computed(() => isDark.value ? '#000' : '#ffffff')
|
|
27
26
|
const fm = useFrontmatter()
|
|
28
27
|
|
|
29
28
|
const { locale } = useI18n()
|
|
@@ -41,14 +40,6 @@ useHead({
|
|
|
41
40
|
],
|
|
42
41
|
meta: [
|
|
43
42
|
{ name: 'description', content: computed(() => siteConfig.value.description) },
|
|
44
|
-
{
|
|
45
|
-
name: 'theme-color',
|
|
46
|
-
content: themeColor,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: 'msapplication-TileColor',
|
|
50
|
-
content: themeColor,
|
|
51
|
-
},
|
|
52
43
|
{
|
|
53
44
|
name: 'generator',
|
|
54
45
|
content: `Valaxy ${pkg.version}`,
|
|
@@ -102,5 +93,9 @@ useSchemaOrg([
|
|
|
102
93
|
<ValaxyThemeApp />
|
|
103
94
|
<ValaxyAddons />
|
|
104
95
|
<ValaxyUserApp />
|
|
105
|
-
<
|
|
96
|
+
<router-view v-slot="{ Component, route }">
|
|
97
|
+
<transition name="app-transition">
|
|
98
|
+
<component :is="Component" :key="route" />
|
|
99
|
+
</transition>
|
|
100
|
+
</router-view>
|
|
106
101
|
</template>
|
|
@@ -16,11 +16,10 @@ pie
|
|
|
16
16
|
import { getCurrentInstance, ref, watch, watchEffect } from 'vue'
|
|
17
17
|
|
|
18
18
|
import { isClient } from '@vueuse/core'
|
|
19
|
+
import { useAppStore } from 'valaxy'
|
|
19
20
|
import { renderMermaid } from '../../modules/mermaid'
|
|
20
21
|
import ShadowRoot from '../internals/ShadowRoot.vue'
|
|
21
22
|
|
|
22
|
-
import { isDark } from '../../composables'
|
|
23
|
-
|
|
24
23
|
const props = defineProps<{
|
|
25
24
|
code: string
|
|
26
25
|
scale?: number
|
|
@@ -31,6 +30,8 @@ const vm = getCurrentInstance()
|
|
|
31
30
|
const el = ref<ShadowRoot>()
|
|
32
31
|
const html = ref('')
|
|
33
32
|
|
|
33
|
+
const appStore = useAppStore()
|
|
34
|
+
|
|
34
35
|
if (isClient) {
|
|
35
36
|
// dynamic import to reduce initial bundle size
|
|
36
37
|
import('mermaid').then(m => m.default)
|
|
@@ -47,7 +48,7 @@ if (isClient) {
|
|
|
47
48
|
mermaid,
|
|
48
49
|
props.code || '',
|
|
49
50
|
{
|
|
50
|
-
theme: props.theme || (isDark
|
|
51
|
+
theme: props.theme || (appStore.isDark ? 'dark' : undefined),
|
|
51
52
|
...vm!.attrs,
|
|
52
53
|
},
|
|
53
54
|
)
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMediaQuery } from '@vueuse/core'
|
|
2
|
+
import { useSidebar } from 'valaxy'
|
|
3
|
+
import { computed } from 'vue'
|
|
2
4
|
|
|
3
5
|
export function useAside() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
const { hasSidebar } = useSidebar()
|
|
7
|
+
const is960 = useMediaQuery('(min-width: 960px)')
|
|
8
|
+
const is1280 = useMediaQuery('(min-width: 1280px)')
|
|
7
9
|
|
|
8
|
-
const isAsideEnabled =
|
|
10
|
+
const isAsideEnabled = computed(() => {
|
|
11
|
+
if (!is1280.value && !is960.value)
|
|
12
|
+
return false
|
|
13
|
+
|
|
14
|
+
return hasSidebar.value ? is1280.value : is960.value
|
|
15
|
+
})
|
|
9
16
|
|
|
10
17
|
return {
|
|
11
18
|
isAsideEnabled,
|
|
@@ -13,6 +13,13 @@ export interface BaseCategory {
|
|
|
13
13
|
total: number
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @en
|
|
18
|
+
* Category list
|
|
19
|
+
*
|
|
20
|
+
* @zh
|
|
21
|
+
* 分类列表
|
|
22
|
+
*/
|
|
16
23
|
export interface CategoryList {
|
|
17
24
|
/**
|
|
18
25
|
* category name
|
|
@@ -27,7 +34,11 @@ export interface CategoryList {
|
|
|
27
34
|
export type Category = CategoryList
|
|
28
35
|
export type Categories = Map<string, Post | CategoryList>
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
/**
|
|
38
|
+
* For theme development, you can use this function to determine whether the category is a category list.
|
|
39
|
+
* @todo write unit test
|
|
40
|
+
* @param category
|
|
41
|
+
*/
|
|
31
42
|
export function isCategoryList(category: any): category is CategoryList {
|
|
32
43
|
return category.children
|
|
33
44
|
}
|
|
@@ -1,44 +1,83 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { UseDarkOptions } from '@vueuse/core'
|
|
2
|
+
import { useDark, useToggle } from '@vueuse/core'
|
|
3
|
+
import { computed } from 'vue'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
export function useValaxyDark(options: {
|
|
6
|
+
/**
|
|
7
|
+
* Options for `useDark`
|
|
8
|
+
* disableTransition default is `true`
|
|
9
|
+
* @see https://vueuse.org/core/useDark
|
|
10
|
+
* @url https://paco.me/writing/disable-theme-transitions
|
|
11
|
+
*/
|
|
12
|
+
useDarkOptions?: UseDarkOptions
|
|
13
|
+
/**
|
|
14
|
+
* Enable circle transition when toggling dark mode
|
|
15
|
+
* Then use `toggleDarkWithTransition` instead of `toggleDark`
|
|
16
|
+
*/
|
|
17
|
+
circleTransition?: boolean
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export function toggleDarkWithTransition(event: MouseEvent, options: { duration?: number, easing?: EffectTiming['easing'] } = {}) {
|
|
10
|
-
// @ts-expect-error startViewTransition is not defined
|
|
11
|
-
if (!document.startViewTransition) {
|
|
12
|
-
toggleDark()
|
|
13
|
-
return
|
|
19
|
+
themeColor?: {
|
|
20
|
+
light?: string
|
|
21
|
+
dark?: string
|
|
14
22
|
}
|
|
23
|
+
} = {}) {
|
|
24
|
+
const isDark = useDark(options.useDarkOptions)
|
|
25
|
+
const toggleDark = useToggle(isDark)
|
|
26
|
+
|
|
27
|
+
const themeColor = computed(() => isDark.value
|
|
28
|
+
? (options.themeColor?.dark || '#000')
|
|
29
|
+
: (options.themeColor?.light || '#fff'))
|
|
30
|
+
|
|
31
|
+
if (options.circleTransition)
|
|
32
|
+
import('valaxy/client/styles/common/view-transition.css')
|
|
15
33
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
transition.ready.then(() => {
|
|
29
|
-
const clipPath = [
|
|
30
|
-
`circle(0px at ${x}px ${y}px)`,
|
|
31
|
-
`circle(${endRadius}px at ${x}px ${y}px)`,
|
|
32
|
-
]
|
|
33
|
-
document.documentElement.animate(
|
|
34
|
-
{
|
|
35
|
-
clipPath: isDark.value ? clipPath.reverse() : clipPath,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
duration: options.duration || 300,
|
|
39
|
-
easing: options.easing || 'ease-in',
|
|
40
|
-
pseudoElement: isDark.value ? '::view-transition-old(root)' : '::view-transition-new(root)',
|
|
41
|
-
},
|
|
34
|
+
function toggleDarkWithTransition(event: MouseEvent, options: { duration?: number, easing?: EffectTiming['easing'] } = {}) {
|
|
35
|
+
// @ts-expect-error startViewTransition is not defined
|
|
36
|
+
if (!document.startViewTransition) {
|
|
37
|
+
toggleDark()
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const x = event.clientX
|
|
42
|
+
const y = event.clientY
|
|
43
|
+
const endRadius = Math.hypot(
|
|
44
|
+
Math.max(x, innerWidth - x),
|
|
45
|
+
Math.max(y, innerHeight - y),
|
|
42
46
|
)
|
|
43
|
-
|
|
47
|
+
|
|
48
|
+
// @ts-expect-error startViewTransition is not defined
|
|
49
|
+
const transition = document.startViewTransition(() => {
|
|
50
|
+
toggleDark()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
transition.ready.then(() => {
|
|
54
|
+
const clipPath = [
|
|
55
|
+
`circle(0px at ${x}px ${y}px)`,
|
|
56
|
+
`circle(${endRadius}px at ${x}px ${y}px)`,
|
|
57
|
+
]
|
|
58
|
+
document.documentElement.animate(
|
|
59
|
+
{
|
|
60
|
+
clipPath: isDark.value ? clipPath.reverse() : clipPath,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
duration: options.duration || 300,
|
|
64
|
+
easing: options.easing || 'ease-in',
|
|
65
|
+
pseudoElement: isDark.value ? '::view-transition-old(root)' : '::view-transition-new(root)',
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
/**
|
|
73
|
+
* Dark mode state, sync with app store
|
|
74
|
+
*
|
|
75
|
+
* You can also use `const appStore = useAppStore(); appStore.isDark` to get the value
|
|
76
|
+
*/
|
|
77
|
+
isDark,
|
|
78
|
+
themeColor,
|
|
79
|
+
|
|
80
|
+
toggleDark,
|
|
81
|
+
toggleDarkWithTransition,
|
|
82
|
+
}
|
|
44
83
|
}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
import { useMediaQuery } from '@vueuse/core'
|
|
1
2
|
import { computed } from 'vue'
|
|
2
3
|
import { useRoute } from 'vue-router'
|
|
3
4
|
|
|
4
5
|
export function useLayout(layout?: string) {
|
|
5
6
|
const route = useRoute()
|
|
6
7
|
if (layout)
|
|
7
|
-
return computed(() => route.meta
|
|
8
|
+
return computed(() => route.meta?.layout === layout)
|
|
8
9
|
else
|
|
9
|
-
return computed(() => route.meta
|
|
10
|
+
return computed(() => route.meta?.layout)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* is mobile media query
|
|
15
|
+
*/
|
|
16
|
+
export function useMobile() {
|
|
17
|
+
return useMediaQuery('(max-width: 768px)')
|
|
10
18
|
}
|
|
@@ -3,6 +3,13 @@ import type { DefaultTheme, Header } from 'valaxy/types'
|
|
|
3
3
|
import { onContentUpdated } from '../../utils'
|
|
4
4
|
import { useFrontmatter, useThemeConfig } from '../..'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @en
|
|
8
|
+
* Menu item, the title menu parsed from the article.
|
|
9
|
+
*
|
|
10
|
+
* @zh
|
|
11
|
+
* 菜单项,从文章中解析出的标题菜单。
|
|
12
|
+
*/
|
|
6
13
|
export type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
|
7
14
|
children?: MenuItem[]
|
|
8
15
|
}
|
|
@@ -105,7 +112,11 @@ export function useOutline() {
|
|
|
105
112
|
* get headers from document directly
|
|
106
113
|
*/
|
|
107
114
|
export function getHeaders(range: Exclude<DefaultTheme.Config['outline'], false>) {
|
|
108
|
-
|
|
115
|
+
// when transition, the markdown-body will be two
|
|
116
|
+
// the first is the old one, the last is the new one
|
|
117
|
+
const markdownBodyElements = document.querySelectorAll('.markdown-body') as NodeListOf<HTMLElement>
|
|
118
|
+
const markdownBody = markdownBodyElements[markdownBodyElements.length - 1]
|
|
119
|
+
const headers = Array.from(markdownBody.querySelectorAll('.markdown-body :where(h1,h2,h3,h4,h5,h6)'))
|
|
109
120
|
.filter(el => el.id && el.hasChildNodes())
|
|
110
121
|
.map((el) => {
|
|
111
122
|
const level = Number(el.tagName[1])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { computed, ref } from 'vue'
|
|
1
|
+
import { computed, ref, watchEffect } from 'vue'
|
|
2
2
|
import { useFrontmatter } from './common'
|
|
3
|
-
import { useLayout } from './layout'
|
|
3
|
+
import { useLayout, useMobile } from './layout'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* helper for sidebar
|
|
@@ -9,6 +9,7 @@ export function useSidebar() {
|
|
|
9
9
|
const isOpen = ref(false)
|
|
10
10
|
const fm = useFrontmatter()
|
|
11
11
|
const layout = useLayout()
|
|
12
|
+
|
|
12
13
|
const hasSidebar = computed(() => {
|
|
13
14
|
return (
|
|
14
15
|
fm.value.sidebar !== false
|
|
@@ -36,3 +37,41 @@ export function useSidebar() {
|
|
|
36
37
|
toggle,
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* dynamic left sidebar logic
|
|
43
|
+
* - sidebar is hidden by default when home or mobile
|
|
44
|
+
* - sidebar is shown by default when not home and not mobile
|
|
45
|
+
* - sidebar can be toggled by user
|
|
46
|
+
*/
|
|
47
|
+
export function useDynamicLeftSidebar() {
|
|
48
|
+
const layout = useLayout()
|
|
49
|
+
const isMobile = useMobile()
|
|
50
|
+
const isOpen = ref(isMobile.value ? false : layout.value !== 'home')
|
|
51
|
+
|
|
52
|
+
watchEffect(() => {
|
|
53
|
+
if (isMobile.value)
|
|
54
|
+
close()
|
|
55
|
+
else if (layout.value !== 'home')
|
|
56
|
+
open()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
function open() {
|
|
60
|
+
isOpen.value = true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function close() {
|
|
64
|
+
isOpen.value = false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function toggle() {
|
|
68
|
+
isOpen.value ? close() : open()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
isOpen,
|
|
73
|
+
open,
|
|
74
|
+
close,
|
|
75
|
+
toggle,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -2,6 +2,15 @@ import { computed } from 'vue'
|
|
|
2
2
|
import type { Post } from '../../types'
|
|
3
3
|
import { useSiteStore } from '../stores'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @en
|
|
7
|
+
* Tag list, key is tag name, value is the object of tag.
|
|
8
|
+
* - count: the number of posts with this tag.
|
|
9
|
+
*
|
|
10
|
+
* @zh
|
|
11
|
+
* 标签列表,键是标签名,值是标签对象。
|
|
12
|
+
* - count: 使用该标签的文章数量。
|
|
13
|
+
*/
|
|
5
14
|
export type Tags = Map<string, {
|
|
6
15
|
count: number
|
|
7
16
|
}>
|
package/client/locales/en.yml
CHANGED
package/client/locales/zh-CN.yml
CHANGED
package/client/main.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// reset styles, load css before app
|
|
2
|
+
// import '@unocss/reset/tailwind.css'
|
|
3
|
+
// https://unocss.dev/guide/style-reset#tailwind-compat
|
|
4
|
+
// minus the background color override for buttons to avoid conflicts with UI frameworks
|
|
5
|
+
import '@unocss/reset/tailwind-compat.css'
|
|
6
|
+
// css
|
|
7
|
+
import './styles/css/css-vars.css'
|
|
8
|
+
import './styles/css/main.css'
|
|
9
|
+
// generate user styles
|
|
10
|
+
import '/@valaxyjs/styles'
|
|
11
|
+
import 'uno.css'
|
|
12
|
+
|
|
1
13
|
import type { ViteSSGContext } from 'vite-ssg'
|
|
2
14
|
import { ViteSSG } from 'vite-ssg'
|
|
3
15
|
|
|
@@ -9,16 +21,6 @@ import AppLink from './components/AppLink.vue'
|
|
|
9
21
|
|
|
10
22
|
import App from './App.vue'
|
|
11
23
|
|
|
12
|
-
// reset styles
|
|
13
|
-
// import '@unocss/reset/tailwind.css'
|
|
14
|
-
// https://unocss.dev/guide/style-reset#tailwind-compat
|
|
15
|
-
// minus the background color override for buttons to avoid conflicts with UI frameworks
|
|
16
|
-
import '@unocss/reset/tailwind-compat.css'
|
|
17
|
-
|
|
18
|
-
// generate user styles
|
|
19
|
-
import '/@valaxyjs/styles'
|
|
20
|
-
import 'uno.css'
|
|
21
|
-
|
|
22
24
|
import setupMain from './setup/main'
|
|
23
25
|
import { setupValaxyDevTools } from './utils/dev'
|
|
24
26
|
|
package/client/setup/main.ts
CHANGED
package/client/setup/mermaid.ts
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
import { defineMermaidSetup } from 'valaxy'
|
|
4
4
|
import type { MermaidOptions } from '../types'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @en
|
|
8
|
+
* Extend the Mermaid configuration.
|
|
9
|
+
*
|
|
10
|
+
* @zh
|
|
11
|
+
* 扩展 Mermaid 配置。
|
|
12
|
+
*/
|
|
6
13
|
export default defineMermaidSetup(() => {
|
|
7
14
|
// eslint-disable-next-line prefer-const
|
|
8
15
|
let injection_return: MermaidOptions = {
|
package/client/setups.ts
CHANGED
|
@@ -2,6 +2,14 @@ import type { ViteSSGContext } from 'vite-ssg'
|
|
|
2
2
|
import type { Awaitable } from '@antfu/utils'
|
|
3
3
|
import type { MermaidOptions } from './types'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @see https://github.com/antfu-collective/vite-ssg
|
|
7
|
+
* @en
|
|
8
|
+
* The context object for the application setup function.
|
|
9
|
+
*
|
|
10
|
+
* @zh
|
|
11
|
+
* 应用 setup 函数的上下文对象。(包括了 ViteSSG context)
|
|
12
|
+
*/
|
|
5
13
|
export type AppContext = ViteSSGContext
|
|
6
14
|
|
|
7
15
|
export type AppSetup = (ctx: AppContext) => Awaitable<void>
|
|
@@ -9,6 +17,13 @@ export type AppSetup = (ctx: AppContext) => Awaitable<void>
|
|
|
9
17
|
// client
|
|
10
18
|
export type MermaidSetup = () => Partial<MermaidOptions> | void
|
|
11
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @en
|
|
22
|
+
* Define the setup function for the client application.
|
|
23
|
+
*
|
|
24
|
+
* @zh
|
|
25
|
+
* 扩展客户端应用的 setup 函数。
|
|
26
|
+
*/
|
|
12
27
|
export function defineAppSetup(fn: AppSetup) {
|
|
13
28
|
return fn
|
|
14
29
|
}
|
package/client/stores/app.ts
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
import { acceptHMRUpdate, defineStore } from 'pinia'
|
|
2
2
|
import { useToggle } from '@vueuse/core'
|
|
3
3
|
import { ref } from 'vue'
|
|
4
|
+
import { useMobile, useThemeConfig, useValaxyDark } from 'valaxy'
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Global store for users
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { useAppStore } from 'valaxy'
|
|
11
|
+
* const appStore = useAppStore()
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
5
14
|
export const useAppStore = defineStore('app', () => {
|
|
15
|
+
const themeConfig = useThemeConfig()
|
|
16
|
+
const { isDark, toggleDark, toggleDarkWithTransition, themeColor } = useValaxyDark(themeConfig.value.valaxyDarkOptions)
|
|
17
|
+
|
|
18
|
+
const isMobile = useMobile()
|
|
6
19
|
const showLoading = ref(true)
|
|
7
20
|
|
|
8
|
-
const [isSidebarOpen, toggleSidebar] = useToggle(false)
|
|
9
21
|
// right sidebar with toc
|
|
10
22
|
const [isRightSidebarOpen, toggleRightSidebar] = useToggle(false)
|
|
11
23
|
|
|
12
24
|
return {
|
|
13
|
-
|
|
25
|
+
isMobile,
|
|
26
|
+
// for dark
|
|
27
|
+
isDark,
|
|
28
|
+
themeColor,
|
|
29
|
+
toggleDark,
|
|
30
|
+
toggleDarkWithTransition,
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
toggleSidebar,
|
|
32
|
+
showLoading,
|
|
17
33
|
|
|
18
34
|
isRightSidebarOpen,
|
|
19
35
|
toggleRightSidebar,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--va-c-bg: #ffffff;
|
|
3
|
+
--va-c-bg-light: #ffffff;
|
|
4
|
+
--va-c-bg-dark: #fafafa;
|
|
5
|
+
--va-c-bg-opacity: rgba(255, 255, 255, 0.8);
|
|
6
|
+
--va-c-bg-soft: #f9f9f9;
|
|
7
|
+
--va-c-bg-alt: #f9f9f9;
|
|
8
|
+
--va-c-bg-mute: #f1f1f1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
html.dark {
|
|
12
|
+
--va-c-bg: #1b1b1f;
|
|
13
|
+
--va-c-bg-light: #202127;
|
|
14
|
+
--va-c-bg-dark: #1a1a1a;
|
|
15
|
+
--va-c-bg-opacity: rgba(0, 0, 0, 0.8);
|
|
16
|
+
--va-c-bg-alt: #161618;
|
|
17
|
+
--va-c-bg-soft: #202127;
|
|
18
|
+
--va-c-bg-mute: #2f2f2f;
|
|
19
|
+
}
|
package/client/styles/index.scss
CHANGED
|
@@ -46,15 +46,6 @@ $light: map.merge(
|
|
|
46
46
|
|
|
47
47
|
"border-color": #222,
|
|
48
48
|
|
|
49
|
-
"c-bg": white,
|
|
50
|
-
"c-bg-light": white,
|
|
51
|
-
"c-bg-dark": #fafafa,
|
|
52
|
-
"c-bg-opacity": rgba(255, 255, 255 , 0.8),
|
|
53
|
-
|
|
54
|
-
"c-bg-soft": #f9f9f9,
|
|
55
|
-
"c-bg-alt": #f9f9f9,
|
|
56
|
-
"c-bg-mute": #f1f1f1,
|
|
57
|
-
|
|
58
49
|
"c-text": #333,
|
|
59
50
|
"c-text-light": #555,
|
|
60
51
|
"c-text-lighter": #666,
|
|
@@ -71,15 +62,6 @@ $dark: map.merge(
|
|
|
71
62
|
(
|
|
72
63
|
"border-color": #e6e6e6,
|
|
73
64
|
|
|
74
|
-
"c-bg": #1b1b1f,
|
|
75
|
-
"c-bg-light": #202127,
|
|
76
|
-
"c-bg-dark": #1a1a1a,
|
|
77
|
-
"c-bg-opacity": rgba(0, 0, 0, 0.8),
|
|
78
|
-
|
|
79
|
-
"c-bg-alt": #161618,
|
|
80
|
-
"c-bg-soft": #202127,
|
|
81
|
-
"c-bg-mute": #2f2f2f,
|
|
82
|
-
|
|
83
65
|
"c-text": #f2f2f2,
|
|
84
66
|
"c-text-light": #ddd,
|
|
85
67
|
"c-text-lighter": #eee,
|
package/client/types/index.ts
CHANGED
|
@@ -3,4 +3,7 @@ import type mermaid from 'mermaid'
|
|
|
3
3
|
|
|
4
4
|
export type UserModule = (ctx: ViteSSGContext) => void
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @see https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-schema
|
|
8
|
+
*/
|
|
6
9
|
export type MermaidOptions = (typeof mermaid.initialize) extends (a: infer A) => any ? A : never
|
package/client/utils/router.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import type { Router } from 'vue-router'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @en
|
|
5
|
+
* Options for scrolling to a target element.
|
|
6
|
+
*
|
|
7
|
+
* @zh
|
|
8
|
+
* 滚动到目标元素的选项。
|
|
9
|
+
*/
|
|
3
10
|
export interface ScrollToOptions {
|
|
4
11
|
/**
|
|
12
|
+
* @en
|
|
13
|
+
* Whether to scroll smoothly.
|
|
14
|
+
*
|
|
15
|
+
* @zh
|
|
5
16
|
* 平滑滚动
|
|
6
17
|
*/
|
|
7
18
|
smooth: boolean
|
|
@@ -11,6 +22,13 @@ export interface ScrollToOptions {
|
|
|
11
22
|
targetPadding: number
|
|
12
23
|
}
|
|
13
24
|
|
|
25
|
+
/**
|
|
26
|
+
* For theme developers, you can use this function to scroll to the target element.
|
|
27
|
+
* For example, when you click the anchor link in the markdown file, it will scroll to the target element.
|
|
28
|
+
* @param el
|
|
29
|
+
* @param hash
|
|
30
|
+
* @param options
|
|
31
|
+
*/
|
|
14
32
|
export function scrollTo(el: HTMLElement, hash: string, options: Partial<ScrollToOptions> = {
|
|
15
33
|
smooth: true,
|
|
16
34
|
targetPadding: -64,
|
package/client/utils/time.ts
CHANGED
|
@@ -10,6 +10,14 @@ export function formatDate(date: string | number | Date, template = 'yyyy-MM-dd'
|
|
|
10
10
|
return format(date, template)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* date-fns format date with 'yyyy-MM-dd HH:mm:ss'
|
|
15
|
+
* @param date
|
|
16
|
+
*/
|
|
17
|
+
export function formatTimestamp(date: string | number | Date): string {
|
|
18
|
+
return format(date, 'yyyy-MM-dd HH:mm:ss')
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
/**
|
|
14
22
|
* sort posts by date
|
|
15
23
|
* @param posts
|