valaxy 0.5.0 → 0.6.0
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/README.md +0 -4
- package/{dist/types/index.mjs → client/app/data.ts} +0 -0
- package/client/components/PostCard.vue +4 -2
- package/client/components/ValaxyBg.vue +1 -1
- package/client/components/ValaxyFooter.vue +1 -1
- package/client/components/ValaxyToc.vue +3 -3
- package/client/composables/outline.ts +181 -0
- package/client/composables/sidebar.ts +58 -1
- package/client/config.ts +30 -7
- package/client/main.ts +4 -1
- package/client/modules/valaxy.ts +33 -8
- package/client/shims.d.ts +6 -1
- package/client/styles/palette.scss +6 -2
- package/client/utils/helper.ts +22 -0
- package/client/utils/sidebar.ts +26 -0
- package/config/index.ts +18 -0
- package/dist/chunk-CP3UCJ2D.js +34 -0
- package/dist/chunk-HCVZ2UUO.mjs +34 -0
- package/dist/{config-7bd43d41.d.ts → config-ad23e743.d.ts} +6 -4
- package/dist/index.d.ts +363 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/node/cli.js +7 -11
- package/dist/node/cli.mjs +7 -11
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +1 -1
- package/dist/node/index.mjs +1 -1
- package/index.ts +3 -0
- package/node/config.ts +9 -23
- package/node/markdown/index.ts +21 -13
- package/node/markdown/markdownToVue.ts +253 -0
- package/node/options.ts +16 -0
- package/node/plugins/extendConfig.ts +4 -3
- package/node/plugins/index.ts +103 -6
- package/node/plugins/preset.ts +6 -6
- package/node/rss.ts +1 -1
- package/node/utils/getGitTimestamp.ts +13 -0
- package/node/utils/index.ts +11 -0
- package/package.json +20 -7
- package/shared/index.ts +1 -0
- package/tsup.config.ts +5 -3
- package/types/config.ts +7 -4
- package/types/data.ts +31 -0
- package/types/index.ts +1 -0
- package/types/posts.ts +1 -1
- package/dist/chunk-RSQONJW3.mjs +0 -86
- package/dist/chunk-XQIGHIAX.js +0 -86
- package/dist/client/index.d.ts +0 -188
- package/dist/client/index.js +0 -1
- package/dist/client/index.mjs +0 -1
- package/dist/posts-32f55e33.d.ts +0 -117
- package/dist/types/index.d.ts +0 -8
- package/dist/types/index.js +0 -1
- package/index.d.ts +0 -3
- package/node/plugins/markdown.ts +0 -54
package/README.md
CHANGED
|
File without changes
|
|
@@ -20,7 +20,8 @@ const { icon, styles } = usePostProperty(props.post.type)
|
|
|
20
20
|
:src="post.cover"
|
|
21
21
|
:alt="t('post.cover')"
|
|
22
22
|
w="40%"
|
|
23
|
-
|
|
23
|
+
h="54"
|
|
24
|
+
class="object-cover object-center md:shadow"
|
|
24
25
|
>
|
|
25
26
|
|
|
26
27
|
<div class="post-card-image-info-text flex-1" w="full">
|
|
@@ -54,7 +55,8 @@ const { icon, styles } = usePostProperty(props.post.type)
|
|
|
54
55
|
</div>
|
|
55
56
|
</div>
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
<!-- always show -->
|
|
59
|
+
<div w="full" class="yun-card-actions flex justify-between" border="t" text="sm">
|
|
58
60
|
<div class="inline-flex">
|
|
59
61
|
<router-link
|
|
60
62
|
v-if="post.categories"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
// this is a runtime toc
|
|
3
|
+
// prebuild toc see composables/outline.ts
|
|
2
4
|
import { onMounted, ref, watch } from 'vue'
|
|
3
5
|
import { useI18n } from 'vue-i18n'
|
|
4
6
|
import { useRoute } from 'vue-router'
|
|
5
7
|
|
|
6
|
-
import type { Header } from '../../
|
|
8
|
+
import type { Header } from '../../types'
|
|
7
9
|
import { useActiveSidebarLinks } from '~/composables'
|
|
8
10
|
import { useConfig } from '~/config'
|
|
9
11
|
|
|
@@ -66,8 +68,6 @@ if (import.meta.hot) {
|
|
|
66
68
|
}, 600)
|
|
67
69
|
})
|
|
68
70
|
}
|
|
69
|
-
|
|
70
|
-
// todo mobile toc widget
|
|
71
71
|
</script>
|
|
72
72
|
|
|
73
73
|
<template>
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { computed, onMounted, onUnmounted, onUpdated } from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
import type { Header } from '../../types'
|
|
5
|
+
import { throttleAndDebounce } from '~/utils'
|
|
6
|
+
|
|
7
|
+
interface HeaderWithChildren extends Header {
|
|
8
|
+
children?: Header[]
|
|
9
|
+
hidden?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface MenuItemWithLinkAndChildren {
|
|
13
|
+
text: string
|
|
14
|
+
link: string
|
|
15
|
+
children?: MenuItemWithLinkAndChildren[]
|
|
16
|
+
hidden?: boolean
|
|
17
|
+
lang?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function resolveHeaders(headers: Header[]) {
|
|
21
|
+
return mapHeaders(groupHeaders(headers))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function groupHeaders(headers: Header[]): HeaderWithChildren[] {
|
|
25
|
+
headers = headers.map(h => Object.assign({}, h))
|
|
26
|
+
|
|
27
|
+
let lastH2: HeaderWithChildren | undefined
|
|
28
|
+
|
|
29
|
+
for (const h of headers) {
|
|
30
|
+
if (h.level === 2)
|
|
31
|
+
lastH2 = h
|
|
32
|
+
|
|
33
|
+
else if (lastH2 && h.level <= 3)
|
|
34
|
+
(lastH2.children || (lastH2.children = [])).push(h)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return headers.filter(h => h.level === 2)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mapHeaders(
|
|
41
|
+
headers: HeaderWithChildren[],
|
|
42
|
+
): MenuItemWithLinkAndChildren[] {
|
|
43
|
+
return headers.map(header => ({
|
|
44
|
+
text: header.title,
|
|
45
|
+
link: `#${header.slug}`,
|
|
46
|
+
children: header.children ? mapHeaders(header.children) : undefined,
|
|
47
|
+
hidden: header.hidden,
|
|
48
|
+
lang: header.lang,
|
|
49
|
+
}))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// magic number to avoid repeated retrieval
|
|
53
|
+
const PAGE_OFFSET = 56
|
|
54
|
+
|
|
55
|
+
export function useOutline() {
|
|
56
|
+
const route = useRoute()
|
|
57
|
+
|
|
58
|
+
const hasOutline = computed(() => {
|
|
59
|
+
return route.meta?.headers?.length > 0
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
hasOutline,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function useActiveAnchor(
|
|
68
|
+
container: Ref<HTMLElement>,
|
|
69
|
+
marker: Ref<HTMLElement>,
|
|
70
|
+
) {
|
|
71
|
+
const onScroll = throttleAndDebounce(setActiveLink, 100)
|
|
72
|
+
|
|
73
|
+
let prevActiveLink: HTMLAnchorElement | null = null
|
|
74
|
+
|
|
75
|
+
onMounted(() => {
|
|
76
|
+
requestAnimationFrame(setActiveLink)
|
|
77
|
+
window.addEventListener('scroll', onScroll)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
onUpdated(() => {
|
|
81
|
+
// sidebar update means a route change
|
|
82
|
+
activateLink(location.hash)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
onUnmounted(() => {
|
|
86
|
+
window.removeEventListener('scroll', onScroll)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
function setActiveLink() {
|
|
90
|
+
const links = [].slice.call(
|
|
91
|
+
container.value.querySelectorAll('.outline-link'),
|
|
92
|
+
) as HTMLAnchorElement[]
|
|
93
|
+
|
|
94
|
+
const anchors = [].slice
|
|
95
|
+
.call(document.querySelectorAll('.content .header-anchor'))
|
|
96
|
+
.filter((anchor: HTMLAnchorElement) => {
|
|
97
|
+
return links.some((link) => {
|
|
98
|
+
return link.hash === anchor.hash && anchor.offsetParent !== null
|
|
99
|
+
})
|
|
100
|
+
}) as HTMLAnchorElement[]
|
|
101
|
+
|
|
102
|
+
const scrollY = window.scrollY
|
|
103
|
+
const innerHeight = window.innerHeight
|
|
104
|
+
const offsetHeight = (document.querySelector('.yun-main') as HTMLElement)!.offsetHeight
|
|
105
|
+
const isBottom = (scrollY + innerHeight) === offsetHeight
|
|
106
|
+
|
|
107
|
+
// console.log(scrollY, innerHeight, offsetHeight)
|
|
108
|
+
// console.log(isBottom)
|
|
109
|
+
|
|
110
|
+
// page bottom - highlight last one
|
|
111
|
+
if (anchors.length && isBottom) {
|
|
112
|
+
activateLink(null)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// isTop
|
|
117
|
+
if (anchors.length && scrollY === 0)
|
|
118
|
+
activateLink('#')
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < anchors.length; i++) {
|
|
121
|
+
const anchor = anchors[i]
|
|
122
|
+
const nextAnchor = anchors[i + 1]
|
|
123
|
+
|
|
124
|
+
const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor)
|
|
125
|
+
|
|
126
|
+
if (isActive) {
|
|
127
|
+
history.replaceState(null, document.title, hash || ' ')
|
|
128
|
+
activateLink(hash)
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function activateLink(hash: string | null) {
|
|
135
|
+
if (prevActiveLink)
|
|
136
|
+
prevActiveLink.classList.remove('active')
|
|
137
|
+
|
|
138
|
+
if (hash !== null) {
|
|
139
|
+
prevActiveLink = container.value.querySelector(
|
|
140
|
+
`a[href="${decodeURIComponent(hash)}"]`,
|
|
141
|
+
) as HTMLAnchorElement
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const activeLink = prevActiveLink
|
|
145
|
+
|
|
146
|
+
const topOffset = 33
|
|
147
|
+
|
|
148
|
+
if (activeLink) {
|
|
149
|
+
activeLink.classList.add('active')
|
|
150
|
+
marker.value.style.top = `${activeLink.offsetTop + topOffset}px`
|
|
151
|
+
marker.value.style.opacity = '1'
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
marker.value.style.top = `${topOffset}px`
|
|
155
|
+
marker.value.style.opacity = '0'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function getAnchorTop(anchor: HTMLAnchorElement): number {
|
|
161
|
+
return anchor.parentElement!.offsetTop - PAGE_OFFSET - 15
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function isAnchorActive(
|
|
165
|
+
index: number,
|
|
166
|
+
anchor: HTMLAnchorElement,
|
|
167
|
+
nextAnchor: HTMLAnchorElement | undefined,
|
|
168
|
+
): [boolean, string | null] {
|
|
169
|
+
const scrollTop = window.scrollY
|
|
170
|
+
|
|
171
|
+
if (index === 0 && scrollTop === 0)
|
|
172
|
+
return [true, null]
|
|
173
|
+
|
|
174
|
+
if (scrollTop < getAnchorTop(anchor))
|
|
175
|
+
return [false, null]
|
|
176
|
+
|
|
177
|
+
if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor))
|
|
178
|
+
return [true, anchor.hash]
|
|
179
|
+
|
|
180
|
+
return [false, null]
|
|
181
|
+
}
|
|
@@ -1,8 +1,53 @@
|
|
|
1
1
|
import type { Ref } from 'vue'
|
|
2
|
-
import { onMounted, onUnmounted } from 'vue'
|
|
2
|
+
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
import { useThemeConfig } from '..'
|
|
5
|
+
import { getSidebar } from '../utils/sidebar'
|
|
6
|
+
import { useFrontmatter } from './common'
|
|
3
7
|
|
|
4
8
|
// todo: refactor
|
|
5
9
|
|
|
10
|
+
export function useSidebar() {
|
|
11
|
+
const route = useRoute()
|
|
12
|
+
const frontmatter = useFrontmatter()
|
|
13
|
+
const themeConfig = useThemeConfig()
|
|
14
|
+
|
|
15
|
+
const isOpen = ref(false)
|
|
16
|
+
|
|
17
|
+
const sidebar = computed(() => {
|
|
18
|
+
const sidebarConfig = themeConfig.value.sidebar
|
|
19
|
+
const relativePath = route.path
|
|
20
|
+
|
|
21
|
+
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const hasSidebar = computed(() => {
|
|
25
|
+
// return frontmatter.value.sidebar !== false && sidebar.value.length > 0
|
|
26
|
+
return frontmatter.value.sidebar !== false
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
function open() {
|
|
30
|
+
isOpen.value = true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function close() {
|
|
34
|
+
isOpen.value = false
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toggle() {
|
|
38
|
+
isOpen.value ? close() : open()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
isOpen,
|
|
43
|
+
sidebar,
|
|
44
|
+
hasSidebar,
|
|
45
|
+
open,
|
|
46
|
+
close,
|
|
47
|
+
toggle,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
6
51
|
export function useActiveSidebarLinks(container: Ref<HTMLElement>, marker: Ref<HTMLElement>) {
|
|
7
52
|
const onScroll = throttleAndDebounce(setActiveLink, 200)
|
|
8
53
|
|
|
@@ -113,3 +158,15 @@ function throttleAndDebounce(fn: () => void, delay: number): () => void {
|
|
|
113
158
|
}
|
|
114
159
|
}
|
|
115
160
|
}
|
|
161
|
+
|
|
162
|
+
export function useOutline() {
|
|
163
|
+
const route = useRoute()
|
|
164
|
+
|
|
165
|
+
const hasOutline = computed(() => {
|
|
166
|
+
return route.meta.headers.length > 0
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
hasOutline,
|
|
171
|
+
}
|
|
172
|
+
}
|
package/client/config.ts
CHANGED
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
// @ts-expect-error virtual module @valaxyjs/config
|
|
2
2
|
import valaxyConfig from '@valaxyjs/config'
|
|
3
|
-
|
|
3
|
+
// @ts-expect-error virtual module @valaxyjs/context
|
|
4
|
+
import valaxyContext from '@valaxyjs/context'
|
|
5
|
+
import type { ComputedRef, InjectionKey, Ref } from 'vue'
|
|
4
6
|
import { computed, inject, readonly, shallowRef } from 'vue'
|
|
5
7
|
import type { ThemeConfig } from 'valaxy-theme-yun'
|
|
6
|
-
import type {
|
|
8
|
+
// import type { RouteMeta } from 'vue-router'
|
|
9
|
+
import type { PageData, ValaxyConfig } from '../types'
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* parse valaxy config
|
|
10
13
|
* @param data
|
|
11
14
|
* @returns
|
|
12
15
|
*/
|
|
13
|
-
function parse(data: string):
|
|
16
|
+
function parse<T=any>(data: string): T {
|
|
14
17
|
const parsed = JSON.parse(data)
|
|
15
|
-
return (import.meta.env.DEV ? readonly(parsed) : parsed) as
|
|
18
|
+
return (import.meta.env.DEV ? readonly(parsed) : parsed) as T
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ValaxyContext {
|
|
22
|
+
userRoot: string
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
export const valaxyConfigSymbol: InjectionKey<ComputedRef<ValaxyConfig<ThemeConfig>>> = Symbol('valaxy:config')
|
|
19
|
-
export const valaxyConfigRef = shallowRef<ValaxyConfig>(parse(valaxyConfig))
|
|
26
|
+
export const valaxyConfigRef = shallowRef<ValaxyConfig>(parse<ValaxyConfig>(valaxyConfig))
|
|
27
|
+
|
|
28
|
+
export const valaxyContextRef = shallowRef<ValaxyContext>(parse<ValaxyContext>(valaxyContext))
|
|
29
|
+
// export const valaxyDataRef = shallowRef<PageData>(parse(valaxyConfig))
|
|
20
30
|
|
|
21
31
|
// hmr
|
|
22
32
|
if (import.meta.hot) {
|
|
23
33
|
// /@valaxyjs/config must be static string
|
|
24
34
|
import.meta.hot.accept('/@valaxyjs/config', (m) => {
|
|
25
|
-
valaxyConfigRef.value = parse(m.default)
|
|
35
|
+
valaxyConfigRef.value = parse<ValaxyConfig>(m.default)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// context
|
|
39
|
+
import.meta.hot.accept('/@valaxyjs/context', (m) => {
|
|
40
|
+
valaxyContextRef.value = parse<ValaxyContext>(m.default)
|
|
26
41
|
})
|
|
27
42
|
}
|
|
28
43
|
|
|
@@ -30,6 +45,10 @@ export function initConfig() {
|
|
|
30
45
|
return computed(() => valaxyConfigRef.value)
|
|
31
46
|
}
|
|
32
47
|
|
|
48
|
+
export function initContext() {
|
|
49
|
+
return computed(() => valaxyContextRef.value)
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
/*
|
|
34
53
|
* get Config
|
|
35
54
|
* @returns
|
|
@@ -37,7 +56,7 @@ export function initConfig() {
|
|
|
37
56
|
export function useConfig() {
|
|
38
57
|
const config = inject(valaxyConfigSymbol)
|
|
39
58
|
if (!config)
|
|
40
|
-
throw new Error('[Valaxy] config not properly injected in
|
|
59
|
+
throw new Error('[Valaxy] config not properly injected in app')
|
|
41
60
|
return config!
|
|
42
61
|
}
|
|
43
62
|
|
|
@@ -50,3 +69,7 @@ export function useThemeConfig() {
|
|
|
50
69
|
return computed(() => config!.value.themeConfig)
|
|
51
70
|
}
|
|
52
71
|
|
|
72
|
+
export interface ValaxyData<T = any> {
|
|
73
|
+
page: Ref<PageData>
|
|
74
|
+
theme: Ref<T>
|
|
75
|
+
}
|
package/client/main.ts
CHANGED
|
@@ -18,7 +18,10 @@ export const createApp = ViteSSG(
|
|
|
18
18
|
{
|
|
19
19
|
routes,
|
|
20
20
|
base: import.meta.env.BASE_URL,
|
|
21
|
-
scrollBehavior() {
|
|
21
|
+
scrollBehavior(to, from) {
|
|
22
|
+
if (to.path !== from.path)
|
|
23
|
+
return { top: 0 }
|
|
24
|
+
},
|
|
22
25
|
},
|
|
23
26
|
(ctx) => {
|
|
24
27
|
// install all modules under `modules/`
|
package/client/modules/valaxy.ts
CHANGED
|
@@ -10,7 +10,10 @@ import { createI18n } from 'vue-i18n'
|
|
|
10
10
|
|
|
11
11
|
import { useStorage } from '@vueuse/core'
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import type { Router } from 'vue-router'
|
|
14
|
+
import type { PageDataPayload } from '../../types'
|
|
15
|
+
import { initConfig, initContext, valaxyConfigSymbol } from '../config'
|
|
16
|
+
import { ensureSuffix } from '@antfu/utils'
|
|
14
17
|
|
|
15
18
|
import type { UserModule } from '~/types'
|
|
16
19
|
|
|
@@ -33,14 +36,16 @@ import messages from '/@valaxyjs/locales'
|
|
|
33
36
|
// import zh from '../../../../../demo/yun/locales/zh-CN.yml'
|
|
34
37
|
// import en from '../../../../../demo/yun/locales/en.yml'
|
|
35
38
|
|
|
36
|
-
function shouldHotReload(payload:
|
|
39
|
+
function shouldHotReload(payload: PageDataPayload): boolean {
|
|
37
40
|
const payloadPath = payload.path.replace(/(\bindex)?\.md$/, '')
|
|
38
41
|
const locationPath = location.pathname.replace(/(\bindex)?\.html$/, '')
|
|
39
|
-
|
|
42
|
+
// console.log(payloadPath, locationPath)
|
|
43
|
+
return ensureSuffix('/', payloadPath) === ensureSuffix('/', locationPath)
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
export const install: UserModule = ({ app, router }) => {
|
|
43
47
|
// inject valaxy config before modules
|
|
48
|
+
const ctx = initContext()
|
|
44
49
|
const config = initConfig()
|
|
45
50
|
app.provide(valaxyConfigSymbol, config)
|
|
46
51
|
|
|
@@ -54,11 +59,31 @@ export const install: UserModule = ({ app, router }) => {
|
|
|
54
59
|
})
|
|
55
60
|
app.use(i18n)
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
router.isReady().then(() => {
|
|
63
|
+
handleHMR(router)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
function pathToUrl(path: string): string {
|
|
67
|
+
return `${location.origin}/@fs${ctx.value.userRoot}/pages${path}.md?import`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
router.beforeEach(async (to) => {
|
|
71
|
+
try {
|
|
72
|
+
const { __pageData } = await import(/* @vite-ignore */pathToUrl(to.path))
|
|
73
|
+
to.meta = Object.assign(to.meta, __pageData)
|
|
74
|
+
}
|
|
75
|
+
catch {}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function handleHMR(router: Router): void {
|
|
80
|
+
// update route.data on HMR updates of active page
|
|
81
|
+
if (import.meta.hot) {
|
|
82
|
+
import.meta.hot!.on('valaxy:pageData', (payload: PageDataPayload) => {
|
|
83
|
+
if (shouldHotReload(payload)) {
|
|
84
|
+
// console.log(payload.pageData.headers)
|
|
85
|
+
Object.assign(router.currentRoute.value.meta, payload.pageData)
|
|
86
|
+
}
|
|
62
87
|
})
|
|
63
88
|
}
|
|
64
89
|
}
|
package/client/shims.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import 'vue-router'
|
|
|
3
3
|
import type { Post } from 'valaxy'
|
|
4
4
|
import type { Header } from '../node/markdown'
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// markdowns can be treat as Vue components
|
|
7
7
|
declare module '*.md' {
|
|
8
8
|
import type { DefineComponent } from 'vue'
|
|
9
9
|
const component: DefineComponent<{}, {}, any>
|
|
@@ -23,6 +23,11 @@ declare module '@valaxyjs/config' {
|
|
|
23
23
|
export default config
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
declare module '@valaxyjs/context' {
|
|
27
|
+
const ctx: string
|
|
28
|
+
export default ctx
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
declare module '/@valaxyjs/locales' {
|
|
27
32
|
const messages: {}
|
|
28
33
|
export default messages
|
|
@@ -37,6 +37,8 @@ $colors: map.merge(
|
|
|
37
37
|
$light: () !default;
|
|
38
38
|
$light: map.merge(
|
|
39
39
|
(
|
|
40
|
+
"c-brand": $c-primary,
|
|
41
|
+
|
|
40
42
|
"border-color": #222,
|
|
41
43
|
|
|
42
44
|
"c-bg": white,
|
|
@@ -44,6 +46,7 @@ $light: map.merge(
|
|
|
44
46
|
"c-bg-dark": #fafafa,
|
|
45
47
|
"c-text": #333,
|
|
46
48
|
"c-text-light": #555,
|
|
49
|
+
"c-text-lighter": #666,
|
|
47
50
|
"c-text-dark": #111,
|
|
48
51
|
|
|
49
52
|
"c-primary-rgb": #{red($c-primary),
|
|
@@ -53,6 +56,7 @@ $light: map.merge(
|
|
|
53
56
|
blue($c-primary)},
|
|
54
57
|
|
|
55
58
|
"c-link": get-css-var("c-primary-dark"),
|
|
59
|
+
"c-divider": rgba(60, 60, 60, 0.2),
|
|
56
60
|
),
|
|
57
61
|
$light
|
|
58
62
|
);
|
|
@@ -67,8 +71,8 @@ $dark: map.merge(
|
|
|
67
71
|
"c-bg-dark": #1a1a1a,
|
|
68
72
|
|
|
69
73
|
"c-text": #f2f2f2,
|
|
70
|
-
"c-text-light": #
|
|
71
|
-
"c-text-lighter": #
|
|
74
|
+
"c-text-light": #ddd,
|
|
75
|
+
"c-text-lighter": #eee,
|
|
72
76
|
"c-text-dark": rgba(#ebebeb, 0.8),
|
|
73
77
|
"c-link": map.get($colors, "primary-light"),
|
|
74
78
|
),
|
package/client/utils/helper.ts
CHANGED
|
@@ -28,3 +28,25 @@ export const wrapTable = (container: HTMLElement | Document = document) => {
|
|
|
28
28
|
wrap(el, 'table-container')
|
|
29
29
|
})
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
export function throttleAndDebounce(fn: () => void, delay: number): () => void {
|
|
33
|
+
let timeout: number
|
|
34
|
+
let called = false
|
|
35
|
+
|
|
36
|
+
return () => {
|
|
37
|
+
if (timeout)
|
|
38
|
+
clearTimeout(timeout)
|
|
39
|
+
|
|
40
|
+
if (!called) {
|
|
41
|
+
fn()
|
|
42
|
+
called = true
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
called = false
|
|
45
|
+
}, delay)
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// @ts-expect-error browser setTimeout
|
|
49
|
+
timeout = setTimeout(fn, delay)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { YunTheme } from 'valaxy-theme-yun'
|
|
2
|
+
import { ensurePrefix } from '@antfu/utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the `Sidebar` from sidebar option. This method will ensure to get correct
|
|
6
|
+
* sidebar config from `MultiSideBarConfig` with various path combinations such
|
|
7
|
+
* as matching `guide/` and `/guide/`. If no matching config was found, it will
|
|
8
|
+
* return empty array.
|
|
9
|
+
*/
|
|
10
|
+
export function getSidebar(
|
|
11
|
+
sidebar: YunTheme.Sidebar,
|
|
12
|
+
path: string,
|
|
13
|
+
) {
|
|
14
|
+
if (Array.isArray(sidebar))
|
|
15
|
+
return sidebar
|
|
16
|
+
|
|
17
|
+
path = ensurePrefix('/', path)
|
|
18
|
+
|
|
19
|
+
for (const dir in sidebar) {
|
|
20
|
+
// make sure the multi sidebar key starts with slash too
|
|
21
|
+
if (path.startsWith(ensurePrefix('/', dir)))
|
|
22
|
+
return sidebar[dir]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return []
|
|
26
|
+
}
|
package/config/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { YunTheme } from 'valaxy-theme-yun'
|
|
2
|
+
import type { UserConfig } from '../types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type config helper
|
|
6
|
+
*/
|
|
7
|
+
export function defineConfig(config: UserConfig<YunTheme.Config>) {
|
|
8
|
+
return config
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type config helper for custom theme config
|
|
13
|
+
*/
|
|
14
|
+
export function defineConfigWithTheme<ThemeConfig>(
|
|
15
|
+
config: UserConfig<ThemeConfig>,
|
|
16
|
+
) {
|
|
17
|
+
return config
|
|
18
|
+
}
|