valaxy 0.3.11 → 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/{src/client → client}/App.vue +0 -0
- package/{src/client/composables/search/index.ts → client/app/data.ts} +0 -0
- package/{src/client → client}/components/AppLink.vue +0 -0
- package/client/components/PostCard.vue +84 -0
- package/{src/client → client}/components/PostList.vue +0 -0
- package/{src/client → client}/components/README.md +0 -0
- package/{src/client → client}/components/ValaxyBg.vue +0 -0
- package/{src/client → client}/components/ValaxyCopyright.vue +0 -0
- package/{src/client → client}/components/ValaxyFooter.vue +1 -1
- package/{src/client → client}/components/ValaxyHamburger.vue +0 -0
- package/{src/client → client}/components/ValaxyMd.vue +1 -5
- package/{src/client → client}/components/ValaxyOverlay.vue +0 -0
- package/{src/client → client}/components/ValaxyPagination.vue +0 -0
- package/{src/client → client}/components/ValaxyRightSidebar.vue +0 -0
- package/{src/client → client}/components/ValaxySidebar.vue +0 -0
- package/{src/client → client}/components/ValaxyToc.vue +3 -3
- package/{src/client → client}/composables/category.ts +0 -0
- package/{src/client → client}/composables/comments/index.ts +0 -0
- package/{src/client → client}/composables/comments/twikoo.ts +0 -0
- package/{src/client → client}/composables/comments/waline.ts +0 -0
- package/{src/client → client}/composables/common.ts +0 -0
- package/{src/client → client}/composables/dark.ts +0 -0
- package/client/composables/features/index.ts +0 -0
- package/{src/client → client}/composables/helper.ts +0 -0
- package/{src/client → client}/composables/index.ts +1 -1
- package/{src/client → client}/composables/layout.ts +0 -0
- package/client/composables/outline.ts +181 -0
- package/{src/client → client}/composables/post.ts +0 -0
- package/client/composables/search/index.ts +0 -0
- package/{src/client → client}/composables/sidebar.ts +68 -9
- package/{src/client → client}/composables/tag.ts +0 -0
- package/{src/client → client}/composables/widgets/aplayer.ts +0 -0
- package/{src/client → client}/composables/widgets/backToTop.ts +0 -0
- package/{src/client → client}/composables/widgets/codepen.ts +0 -0
- package/{src/client → client}/composables/widgets/index.ts +0 -0
- package/client/config.ts +75 -0
- package/{src/client → client}/index.html +0 -0
- package/{src/client → client}/index.ts +0 -0
- package/{src/client → client}/layouts/404.vue +0 -0
- package/{src/client → client}/layouts/README.md +0 -0
- package/{src/client → client}/locales/README.md +0 -0
- package/{src/client → client}/locales/en.yml +1 -0
- package/{src/client → client}/locales/zh-CN.yml +4 -3
- package/{src/client → client}/main.ts +8 -1
- package/{src/client → client}/modules/README.md +0 -0
- package/{src/client → client}/modules/nprogress.ts +0 -0
- package/{src/client → client}/modules/pinia.ts +0 -0
- package/{src/client → client}/modules/valaxy.ts +34 -9
- package/{src/client → client}/pages/README.md +0 -0
- package/{src/client → client}/pages/[...all].vue +0 -0
- package/{src/client → client}/pages/hi/[name].vue +0 -0
- package/{src/client → client}/pages/index.vue +0 -0
- package/{src/client → client}/pages/page/[page].vue +0 -0
- package/{src/client → client}/shims.d.ts +7 -1
- package/{src/client → client}/stores/app.ts +0 -0
- package/{src/client → client}/stores/user.ts +0 -0
- package/{src/client → client}/styles/common/button.scss +0 -0
- package/{src/client → client}/styles/common/code.scss +0 -0
- package/{src/client → client}/styles/common/custom-blocks.scss +0 -0
- package/{src/client → client}/styles/common/hamburger.scss +0 -0
- package/{src/client → client}/styles/common/markdown.scss +5 -1
- package/client/styles/common/scrollbar.scss +28 -0
- package/{src/client → client}/styles/common/sidebar.scss +0 -0
- package/{src/client → client}/styles/common/transition.scss +0 -0
- package/{src/client → client}/styles/css-vars.scss +0 -0
- package/{src/client → client}/styles/global/helper.scss +0 -0
- package/{src/client → client}/styles/global/i18n.scss +0 -0
- package/{src/client → client}/styles/global/index.scss +0 -0
- package/{src/client → client}/styles/global/nprogress.scss +0 -0
- package/{src/client → client}/styles/global/reset.scss +0 -0
- package/{src/client → client}/styles/index.scss +0 -0
- package/{src/client → client}/styles/mixins/config.scss +0 -0
- package/{src/client → client}/styles/mixins/index.scss +0 -0
- package/{src/client → client}/styles/mixins/size.scss +0 -0
- package/{src/client → client}/styles/mixins/variable.scss +0 -0
- package/{src/client → client}/styles/palette.scss +6 -2
- package/client/styles/third/katex.scss +3 -0
- package/{src/client → client}/styles/vars.scss +0 -0
- package/{src/client → client}/styles/widgets/banner.scss +0 -0
- package/{src/client → client}/types.ts +0 -0
- package/{src/client → client}/utils/helper.ts +22 -0
- package/{src/client → client}/utils/index.ts +0 -0
- package/client/utils/sidebar.ts +26 -0
- package/{src/client → client}/utils/time.ts +0 -0
- package/config/index.ts +18 -0
- package/dist/chunk-CP3UCJ2D.js +34 -0
- package/dist/chunk-EAN2KU6W.mjs +1 -0
- package/dist/chunk-HCVZ2UUO.mjs +34 -0
- package/dist/chunk-U5OMNIOK.js +1 -0
- package/dist/{config-de04677b.d.ts → config-ad23e743.d.ts} +28 -14
- package/dist/index.d.ts +67 -111
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- 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/{src/index.ts → index.ts} +1 -0
- package/{src/node → node}/build.ts +0 -0
- package/{src/node → node}/cli.ts +3 -2
- package/node/config.ts +156 -0
- package/{src/node → node}/index.ts +0 -0
- package/{src/node → node}/markdown/check.ts +0 -0
- package/{src/node → node}/markdown/highlight.ts +0 -0
- package/{src/node → node}/markdown/index.ts +21 -13
- package/{src/node → node}/markdown/markdown-it/container.ts +0 -0
- package/{src/node → node}/markdown/markdown-it/headings.ts +0 -0
- package/{src/node → node}/markdown/markdown-it/highlightLines.ts +0 -0
- package/{src/node → node}/markdown/markdown-it/katex.ts +0 -0
- package/{src/node → node}/markdown/markdown-it/parseHeader.ts +0 -0
- package/node/markdown/markdownToVue.ts +253 -0
- package/{src/node → node}/markdown/slugify.ts +0 -0
- package/{src/node → node}/options.ts +18 -2
- package/{src/node → node}/plugins/extendConfig.ts +6 -3
- package/node/plugins/index.ts +224 -0
- package/{src/node → node}/plugins/preset.ts +6 -36
- package/{src/node → node}/plugins/unocss.ts +0 -0
- package/{src/node → node}/plugins/valaxy.ts +0 -0
- package/{src/node → node}/rss.ts +1 -1
- package/{src/node → node}/server.ts +6 -4
- package/{src/node → node}/shims.d.ts +0 -0
- package/{src/node → node}/utils/cli.ts +1 -1
- package/node/utils/getGitTimestamp.ts +13 -0
- package/node/utils/index.ts +59 -0
- package/node/utils/net.ts +20 -0
- package/{src/node → node}/vite.ts +5 -1
- package/package.json +33 -13
- package/shared/index.ts +1 -0
- package/tsup.config.ts +7 -4
- package/{src/types → types}/config.ts +31 -108
- package/types/data.ts +31 -0
- package/{src/types → types}/index.ts +1 -0
- package/{src/types → types}/posts.ts +6 -1
- package/dist/chunk-6LIOFBAA.mjs +0 -1
- package/dist/chunk-ABPVSNYI.js +0 -83
- package/dist/chunk-QOANGHSR.mjs +0 -83
- package/dist/chunk-V3BMKLEW.js +0 -1
- package/src/client/components/PostCard.vue +0 -68
- package/src/client/composables/features/index.ts +0 -1
- package/src/client/composables/features/katex.ts +0 -15
- package/src/client/composables/search/algolia.ts +0 -115
- package/src/client/config.ts +0 -51
- package/src/client/modules/pwa.ts +0 -12
- package/src/client/styles/common/scrollbar.scss +0 -34
- package/src/node/config.ts +0 -52
- package/src/node/plugins/index.ts +0 -120
- package/src/node/plugins/markdown.ts +0 -57
- package/src/node/utils/index.ts +0 -26
package/README.md
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useI18n } from 'vue-i18n'
|
|
3
|
+
import type { Post } from '../../types'
|
|
4
|
+
import { usePostProperty } from '~/composables'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
post: Post
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const { t } = useI18n()
|
|
11
|
+
|
|
12
|
+
const { icon, styles } = usePostProperty(props.post.type)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<YunCard m="y-4 auto" :class="post.cover ? 'post-card-image' : 'post-card'" :style="styles">
|
|
17
|
+
<div class="flex flex-1 of-hidden justify-start items-start post-card-info" w="full">
|
|
18
|
+
<img
|
|
19
|
+
v-if="post.cover"
|
|
20
|
+
:src="post.cover"
|
|
21
|
+
:alt="t('post.cover')"
|
|
22
|
+
w="40%"
|
|
23
|
+
h="54"
|
|
24
|
+
class="object-cover object-center md:shadow"
|
|
25
|
+
>
|
|
26
|
+
|
|
27
|
+
<div class="post-card-image-info-text flex-1" w="full">
|
|
28
|
+
<div class="flex flex-col flex-1 justify-center items-center" w="full">
|
|
29
|
+
<AppLink
|
|
30
|
+
class="post-title-link"
|
|
31
|
+
:to="post.path || ''"
|
|
32
|
+
m="t-3"
|
|
33
|
+
>
|
|
34
|
+
<div class="flex justify-center items-center title text-2xl" font="serif black">
|
|
35
|
+
<div v-if="post.type" class="inline-flex" m="r-1" :class="icon" />{{ post.title }}
|
|
36
|
+
</div>
|
|
37
|
+
</AppLink>
|
|
38
|
+
|
|
39
|
+
<YunPostMeta :frontmatter="post" />
|
|
40
|
+
|
|
41
|
+
<div v-if="post.excerpt" class="markdown-body" text="left" w="full" p="x-6 lt-sm:4" v-html="post.excerpt" />
|
|
42
|
+
<div m="b-5" />
|
|
43
|
+
|
|
44
|
+
<a
|
|
45
|
+
v-if="post.url"
|
|
46
|
+
:href="post.url"
|
|
47
|
+
class="post-link-btn shadow hover:shadow-md"
|
|
48
|
+
rounded
|
|
49
|
+
target="_blank"
|
|
50
|
+
m="b-4"
|
|
51
|
+
>
|
|
52
|
+
{{ t('post.view_link') }}
|
|
53
|
+
</a>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- always show -->
|
|
59
|
+
<div w="full" class="yun-card-actions flex justify-between" border="t" text="sm">
|
|
60
|
+
<div class="inline-flex">
|
|
61
|
+
<router-link
|
|
62
|
+
v-if="post.categories"
|
|
63
|
+
:to="{
|
|
64
|
+
path: '/categories/',
|
|
65
|
+
query: { category: Array.isArray(post.categories) ? post.categories[post.categories.length - 1] : post.categories },
|
|
66
|
+
}"
|
|
67
|
+
class="post-categories inline-flex justify-center items-center" m="l-2"
|
|
68
|
+
>
|
|
69
|
+
<div m="x-1" i-ri-folder-2-line />
|
|
70
|
+
{{ Array.isArray(post.categories) ? post.categories.join(' > ') : post.categories }}
|
|
71
|
+
</router-link>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="post-tags inline-flex" m="r-2">
|
|
75
|
+
<template v-if="post.tags">
|
|
76
|
+
<router-link v-for="tag, i in post.tags" :key="i" :to="{ path: '/tags/', query: { tag } }" m="x-1" class="post-tag inline-flex justify-center items-center">
|
|
77
|
+
<div m="r-1" i-ri-price-tag-3-line />
|
|
78
|
+
{{ tag }}
|
|
79
|
+
</router-link>
|
|
80
|
+
</template>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</YunCard>
|
|
84
|
+
</template>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Post } from 'valaxy'
|
|
3
3
|
import { onMounted, ref } from 'vue'
|
|
4
4
|
import { useI18n } from 'vue-i18n'
|
|
5
|
-
import { useAplayer, useCodePen
|
|
5
|
+
import { useAplayer, useCodePen } from '~/composables'
|
|
6
6
|
import { wrapTable } from '~/utils'
|
|
7
7
|
|
|
8
8
|
const props = defineProps<{
|
|
@@ -21,10 +21,6 @@ onMounted(() => {
|
|
|
21
21
|
updateDom()
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
// features
|
|
25
|
-
if (props.frontmatter.katex)
|
|
26
|
-
useKatex()
|
|
27
|
-
|
|
28
24
|
// widgets
|
|
29
25
|
if (props.frontmatter.aplayer)
|
|
30
26
|
useAplayer()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -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>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -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
|
|
|
@@ -42,14 +87,16 @@ export function useActiveSidebarLinks(container: Ref<HTMLElement>, marker: Ref<H
|
|
|
42
87
|
: container.value.querySelector(`.va-toc a[href="${hash}"]`) as HTMLAnchorElement)
|
|
43
88
|
|
|
44
89
|
// marker animation
|
|
45
|
-
if (
|
|
46
|
-
activeLink
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
90
|
+
if (marker.value) {
|
|
91
|
+
if (activeLink) {
|
|
92
|
+
activeLink.classList.add('active')
|
|
93
|
+
marker.value.style.opacity = '1'
|
|
94
|
+
marker.value.style.top = `${activeLink.offsetTop + 2}px`
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
marker.value.style.opacity = '0'
|
|
98
|
+
marker.value.style.top = '54px'
|
|
99
|
+
}
|
|
53
100
|
}
|
|
54
101
|
}
|
|
55
102
|
|
|
@@ -111,3 +158,15 @@ function throttleAndDebounce(fn: () => void, delay: number): () => void {
|
|
|
111
158
|
}
|
|
112
159
|
}
|
|
113
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
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/client/config.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// @ts-expect-error virtual module @valaxyjs/config
|
|
2
|
+
import valaxyConfig from '@valaxyjs/config'
|
|
3
|
+
// @ts-expect-error virtual module @valaxyjs/context
|
|
4
|
+
import valaxyContext from '@valaxyjs/context'
|
|
5
|
+
import type { ComputedRef, InjectionKey, Ref } from 'vue'
|
|
6
|
+
import { computed, inject, readonly, shallowRef } from 'vue'
|
|
7
|
+
import type { ThemeConfig } from 'valaxy-theme-yun'
|
|
8
|
+
// import type { RouteMeta } from 'vue-router'
|
|
9
|
+
import type { PageData, ValaxyConfig } from '../types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* parse valaxy config
|
|
13
|
+
* @param data
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function parse<T=any>(data: string): T {
|
|
17
|
+
const parsed = JSON.parse(data)
|
|
18
|
+
return (import.meta.env.DEV ? readonly(parsed) : parsed) as T
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ValaxyContext {
|
|
22
|
+
userRoot: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const valaxyConfigSymbol: InjectionKey<ComputedRef<ValaxyConfig<ThemeConfig>>> = Symbol('valaxy:config')
|
|
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))
|
|
30
|
+
|
|
31
|
+
// hmr
|
|
32
|
+
if (import.meta.hot) {
|
|
33
|
+
// /@valaxyjs/config must be static string
|
|
34
|
+
import.meta.hot.accept('/@valaxyjs/config', (m) => {
|
|
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)
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function initConfig() {
|
|
45
|
+
return computed(() => valaxyConfigRef.value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function initContext() {
|
|
49
|
+
return computed(() => valaxyContextRef.value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* get Config
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
export function useConfig() {
|
|
57
|
+
const config = inject(valaxyConfigSymbol)
|
|
58
|
+
if (!config)
|
|
59
|
+
throw new Error('[Valaxy] config not properly injected in app')
|
|
60
|
+
return config!
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* getThemeConfig
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
export function useThemeConfig() {
|
|
68
|
+
const config = useConfig()
|
|
69
|
+
return computed(() => config!.value.themeConfig)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ValaxyData<T = any> {
|
|
73
|
+
page: Ref<PageData>
|
|
74
|
+
theme: Ref<T>
|
|
75
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -43,6 +43,7 @@ post:
|
|
|
43
43
|
related_posts: 相关文章
|
|
44
44
|
view_link: 查看链接
|
|
45
45
|
read_more: 阅读更多
|
|
46
|
+
cover: 封面
|
|
46
47
|
copyright:
|
|
47
48
|
author: 本文作者
|
|
48
49
|
link: 本文链接
|
|
@@ -59,9 +60,9 @@ footer:
|
|
|
59
60
|
total_visitors: 总访客量
|
|
60
61
|
|
|
61
62
|
counter:
|
|
62
|
-
archives: 暂无日志 | 共计 {count} 篇日志
|
|
63
|
-
categories: 暂无分类 | 共计 {count} 个分类
|
|
64
|
-
tags: 暂无标签 | 共计 {count} 个标签
|
|
63
|
+
archives: 暂无日志 | 共计 1 篇日志 | 共计 {count} 篇日志
|
|
64
|
+
categories: 暂无分类 | 共计 1 个分类 | 共计 {count} 个分类
|
|
65
|
+
tags: 暂无标签 | 共计 1 个标签 | 共计 {count} 个标签
|
|
65
66
|
albums:
|
|
66
67
|
zero: 暂无相册
|
|
67
68
|
one: 共计 1 个相册
|
|
@@ -15,7 +15,14 @@ const routes = setupLayouts(__DEV__ ? generatedRoutes : generatedRoutes.filter(i
|
|
|
15
15
|
// https://github.com/antfu/vite-ssg
|
|
16
16
|
export const createApp = ViteSSG(
|
|
17
17
|
App,
|
|
18
|
-
{
|
|
18
|
+
{
|
|
19
|
+
routes,
|
|
20
|
+
base: import.meta.env.BASE_URL,
|
|
21
|
+
scrollBehavior(to, from) {
|
|
22
|
+
if (to.path !== from.path)
|
|
23
|
+
return { top: 0 }
|
|
24
|
+
},
|
|
25
|
+
},
|
|
19
26
|
(ctx) => {
|
|
20
27
|
// install all modules under `modules/`
|
|
21
28
|
Object.values(import.meta.globEager('./modules/*.ts')).forEach(i => i.install?.(ctx))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|