vitepress-theme-element-plus 0.0.3 → 0.0.4
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 +3 -3
- package/client/components/A11yTag.vue +29 -29
- package/client/components/ApiTyping.vue +54 -54
- package/client/components/Backdrop.vue +41 -41
- package/client/components/Bili.vue +94 -94
- package/client/components/Content.vue +148 -150
- package/client/components/DeprecatedTag.vue +19 -19
- package/client/components/Doc.vue +181 -181
- package/client/components/DocAside.vue +46 -46
- package/client/components/DocAsideOutline.vue +82 -82
- package/client/components/DocFooter.vue +159 -159
- package/client/components/Footer.vue +77 -77
- package/client/components/FooterCopyright.vue +27 -27
- package/client/components/Layout.vue +156 -156
- package/client/components/Link.vue +41 -41
- package/client/components/LocalNav.vue +160 -160
- package/client/components/Nav.vue +69 -69
- package/client/components/NavBar.vue +203 -203
- package/client/components/NavBarTitle.vue +75 -75
- package/client/components/Sidebar.vue +129 -129
- package/client/components/SidebarGroup.vue +51 -51
- package/client/components/SidebarItem.vue +302 -302
- package/client/components/Tag.vue +25 -25
- package/client/components/VPNavBarSearch.vue +23 -23
- package/client/components/VersionTag.vue +18 -18
- package/client/hooks/useBackTop.ts +71 -71
- package/client/hooks/useLangs.ts +50 -50
- package/client/hooks/useSidebar.ts +93 -18
- package/client/hooks/useSidebarControl.ts +78 -78
- package/client/hooks/useSize.ts +69 -69
- package/client/utils/client/common.ts +49 -49
- package/client/utils/client/outline.ts +113 -113
- package/client/utils/common.ts +90 -90
- package/index.ts +26 -26
- package/package.json +73 -73
- package/shared/constants.ts +3 -3
- package/styles/base.scss +37 -37
- package/styles/code.scss +282 -282
- package/styles/doc-content.scss +161 -161
- package/styles/index.scss +69 -69
- package/styles/tag-content.scss +30 -30
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import VPNavBarSearch from 'vitepress/dist/client/theme-default/components/VPNavBarSearch.vue'
|
|
3
|
-
// compatible with vitepress-plugin-pagefind
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<template>
|
|
7
|
-
<VPNavBarSearch />
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<style>
|
|
11
|
-
@media (min-width: 768px) {
|
|
12
|
-
.VPNavBarSearch.VPNavBarSearch {
|
|
13
|
-
flex-grow: unset;
|
|
14
|
-
padding-right: 24px;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
@media (min-width: 960px) {
|
|
19
|
-
.VPNavBarSearch.VPNavBarSearch {
|
|
20
|
-
padding-right: 32px;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
</style>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import VPNavBarSearch from 'vitepress/dist/client/theme-default/components/VPNavBarSearch.vue'
|
|
3
|
+
// compatible with vitepress-plugin-pagefind
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<VPNavBarSearch />
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
@media (min-width: 768px) {
|
|
12
|
+
.VPNavBarSearch.VPNavBarSearch {
|
|
13
|
+
flex-grow: unset;
|
|
14
|
+
padding-right: 24px;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (min-width: 960px) {
|
|
19
|
+
.VPNavBarSearch.VPNavBarSearch {
|
|
20
|
+
padding-right: 32px;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { ElTag } from 'element-plus'
|
|
3
|
-
|
|
4
|
-
defineProps<{
|
|
5
|
-
version: string
|
|
6
|
-
}>()
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<template>
|
|
10
|
-
<ElTag
|
|
11
|
-
size="small"
|
|
12
|
-
effect="plain"
|
|
13
|
-
hit
|
|
14
|
-
round
|
|
15
|
-
>
|
|
16
|
-
{{ version }}
|
|
17
|
-
</ElTag>
|
|
18
|
-
</template>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ElTag } from 'element-plus'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
version: string
|
|
6
|
+
}>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<ElTag
|
|
11
|
+
size="small"
|
|
12
|
+
effect="plain"
|
|
13
|
+
hit
|
|
14
|
+
round
|
|
15
|
+
>
|
|
16
|
+
{{ version }}
|
|
17
|
+
</ElTag>
|
|
18
|
+
</template>
|
|
@@ -1,74 +1,74 @@
|
|
|
1
1
|
import { isClient } from '@vueuse/core'
|
|
2
2
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
3
3
|
import { throttle } from '../utils/throttle'
|
|
4
|
-
|
|
5
|
-
const threshold = 960
|
|
6
|
-
|
|
7
|
-
const cubic = (value: number): number => value ** 3
|
|
8
|
-
function easeInOutCubic(value: number): number {
|
|
9
|
-
return value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function useBackTop(offset = 200) {
|
|
13
|
-
const shouldShow = ref(false)
|
|
14
|
-
const throttleResize = throttle(onResize, 300)
|
|
15
|
-
const throttleScroll = throttle(onScroll, 160)
|
|
16
|
-
|
|
17
|
-
onMounted(() => {
|
|
18
|
-
if (!isClient)
|
|
19
|
-
return
|
|
20
|
-
onResize()
|
|
21
|
-
onScroll()
|
|
22
|
-
window.addEventListener('resize', throttleResize)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
onBeforeUnmount(() => {
|
|
26
|
-
if (!isClient)
|
|
27
|
-
return
|
|
28
|
-
window.removeEventListener('resize', throttleResize)
|
|
29
|
-
window.removeEventListener('scroll', throttleScroll)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
const scrollToTop = () => {
|
|
33
|
-
const beginTime = Date.now()
|
|
34
|
-
const beginValue = document.documentElement.scrollTop
|
|
35
|
-
const rAF = window.requestAnimationFrame
|
|
36
|
-
const frameFunc = () => {
|
|
37
|
-
const progress = (Date.now() - beginTime) / 500
|
|
38
|
-
if (progress < 1) {
|
|
39
|
-
document.documentElement.scrollTop
|
|
40
|
-
= beginValue * (1 - easeInOutCubic(progress))
|
|
41
|
-
rAF(frameFunc)
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
document.documentElement.scrollTop = 0
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
rAF(frameFunc)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function onResize() {
|
|
51
|
-
if (!isClient)
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
const { clientWidth } = document.body
|
|
55
|
-
|
|
56
|
-
if (clientWidth < threshold) {
|
|
57
|
-
window.addEventListener('scroll', throttleScroll)
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
window.removeEventListener('scroll', throttleScroll)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function onScroll() {
|
|
65
|
-
if (!isClient)
|
|
66
|
-
return
|
|
67
|
-
shouldShow.value = document.documentElement.scrollTop > offset
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
shouldShow,
|
|
72
|
-
scrollToTop,
|
|
73
|
-
}
|
|
74
|
-
}
|
|
4
|
+
|
|
5
|
+
const threshold = 960
|
|
6
|
+
|
|
7
|
+
const cubic = (value: number): number => value ** 3
|
|
8
|
+
function easeInOutCubic(value: number): number {
|
|
9
|
+
return value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useBackTop(offset = 200) {
|
|
13
|
+
const shouldShow = ref(false)
|
|
14
|
+
const throttleResize = throttle(onResize, 300)
|
|
15
|
+
const throttleScroll = throttle(onScroll, 160)
|
|
16
|
+
|
|
17
|
+
onMounted(() => {
|
|
18
|
+
if (!isClient)
|
|
19
|
+
return
|
|
20
|
+
onResize()
|
|
21
|
+
onScroll()
|
|
22
|
+
window.addEventListener('resize', throttleResize)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
onBeforeUnmount(() => {
|
|
26
|
+
if (!isClient)
|
|
27
|
+
return
|
|
28
|
+
window.removeEventListener('resize', throttleResize)
|
|
29
|
+
window.removeEventListener('scroll', throttleScroll)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const scrollToTop = () => {
|
|
33
|
+
const beginTime = Date.now()
|
|
34
|
+
const beginValue = document.documentElement.scrollTop
|
|
35
|
+
const rAF = window.requestAnimationFrame
|
|
36
|
+
const frameFunc = () => {
|
|
37
|
+
const progress = (Date.now() - beginTime) / 500
|
|
38
|
+
if (progress < 1) {
|
|
39
|
+
document.documentElement.scrollTop
|
|
40
|
+
= beginValue * (1 - easeInOutCubic(progress))
|
|
41
|
+
rAF(frameFunc)
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
document.documentElement.scrollTop = 0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
rAF(frameFunc)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function onResize() {
|
|
51
|
+
if (!isClient)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
const { clientWidth } = document.body
|
|
55
|
+
|
|
56
|
+
if (clientWidth < threshold) {
|
|
57
|
+
window.addEventListener('scroll', throttleScroll)
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
window.removeEventListener('scroll', throttleScroll)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function onScroll() {
|
|
65
|
+
if (!isClient)
|
|
66
|
+
return
|
|
67
|
+
shouldShow.value = document.documentElement.scrollTop > offset
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
shouldShow,
|
|
72
|
+
scrollToTop,
|
|
73
|
+
}
|
|
74
|
+
}
|
package/client/hooks/useLangs.ts
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { useData } from 'vitepress'
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import { ensureStartingSlash } from '../utils/common'
|
|
4
|
-
|
|
5
|
-
export function useLangs({ correspondingLink = false } = {}) {
|
|
6
|
-
const { site, localeIndex, page, theme, hash } = useData()
|
|
7
|
-
const currentLang = computed(() => ({
|
|
8
|
-
label: site.value.locales[localeIndex.value]?.label,
|
|
9
|
-
link:
|
|
10
|
-
site.value.locales[localeIndex.value]?.link
|
|
11
|
-
|| (localeIndex.value === 'root' ? '/' : `/${localeIndex.value}/`),
|
|
12
|
-
}))
|
|
13
|
-
|
|
14
|
-
const localeLinks = computed(() =>
|
|
15
|
-
Object.entries(site.value.locales).flatMap(([key, value]) =>
|
|
16
|
-
currentLang.value.label === value.label
|
|
17
|
-
? []
|
|
18
|
-
: {
|
|
19
|
-
text: value.label,
|
|
20
|
-
link:
|
|
21
|
-
normalizeLink(
|
|
22
|
-
value.link || (key === 'root' ? '/' : `/${key}/`),
|
|
23
|
-
theme.value.i18nRouting !== false && correspondingLink,
|
|
24
|
-
page.value.relativePath.slice(
|
|
25
|
-
currentLang.value.link.length - 1,
|
|
26
|
-
),
|
|
27
|
-
!site.value.cleanUrls,
|
|
28
|
-
) + hash.value,
|
|
29
|
-
},
|
|
30
|
-
),
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
return { localeLinks, currentLang }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function normalizeLink(
|
|
37
|
-
link: string,
|
|
38
|
-
addPath: boolean,
|
|
39
|
-
path: string,
|
|
40
|
-
addExt: boolean,
|
|
41
|
-
) {
|
|
42
|
-
return addPath
|
|
43
|
-
? link.replace(/\/$/, '')
|
|
44
|
-
+ ensureStartingSlash(
|
|
45
|
-
path
|
|
46
|
-
.replace(/(^|\/)index\.md$/, '$1')
|
|
47
|
-
.replace(/\.md$/, addExt ? '.html' : ''),
|
|
48
|
-
)
|
|
49
|
-
: link
|
|
50
|
-
}
|
|
1
|
+
import { useData } from 'vitepress'
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { ensureStartingSlash } from '../utils/common'
|
|
4
|
+
|
|
5
|
+
export function useLangs({ correspondingLink = false } = {}) {
|
|
6
|
+
const { site, localeIndex, page, theme, hash } = useData()
|
|
7
|
+
const currentLang = computed(() => ({
|
|
8
|
+
label: site.value.locales[localeIndex.value]?.label,
|
|
9
|
+
link:
|
|
10
|
+
site.value.locales[localeIndex.value]?.link
|
|
11
|
+
|| (localeIndex.value === 'root' ? '/' : `/${localeIndex.value}/`),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
const localeLinks = computed(() =>
|
|
15
|
+
Object.entries(site.value.locales).flatMap(([key, value]) =>
|
|
16
|
+
currentLang.value.label === value.label
|
|
17
|
+
? []
|
|
18
|
+
: {
|
|
19
|
+
text: value.label,
|
|
20
|
+
link:
|
|
21
|
+
normalizeLink(
|
|
22
|
+
value.link || (key === 'root' ? '/' : `/${key}/`),
|
|
23
|
+
theme.value.i18nRouting !== false && correspondingLink,
|
|
24
|
+
page.value.relativePath.slice(
|
|
25
|
+
currentLang.value.link.length - 1,
|
|
26
|
+
),
|
|
27
|
+
!site.value.cleanUrls,
|
|
28
|
+
) + hash.value,
|
|
29
|
+
},
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return { localeLinks, currentLang }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeLink(
|
|
37
|
+
link: string,
|
|
38
|
+
addPath: boolean,
|
|
39
|
+
path: string,
|
|
40
|
+
addExt: boolean,
|
|
41
|
+
) {
|
|
42
|
+
return addPath
|
|
43
|
+
? link.replace(/\/$/, '')
|
|
44
|
+
+ ensureStartingSlash(
|
|
45
|
+
path
|
|
46
|
+
.replace(/(^|\/)index\.md$/, '$1')
|
|
47
|
+
.replace(/\.md$/, addExt ? '.html' : ''),
|
|
48
|
+
)
|
|
49
|
+
: link
|
|
50
|
+
}
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
+
import type { DefaultTheme } from 'vitepress'
|
|
1
2
|
import { useMediaQuery } from '@vueuse/core'
|
|
2
3
|
import { useData } from 'vitepress'
|
|
3
4
|
import { computed, onMounted, onUnmounted, ref, watch, watchEffect } from 'vue'
|
|
4
5
|
import { NOT_ARTICLE_LAYOUTS } from '../../shared/constants'
|
|
6
|
+
import { ensureStartingSlash } from '../utils/common'
|
|
5
7
|
|
|
6
8
|
export function useSidebar() {
|
|
7
|
-
const { frontmatter, theme } = useData()
|
|
9
|
+
const { frontmatter, theme, page } = useData()
|
|
8
10
|
const is960 = useMediaQuery('(min-width: 960px)')
|
|
9
11
|
const isOpen = ref(false)
|
|
10
|
-
const
|
|
12
|
+
const sidebar = ref<DefaultTheme.SidebarItem[]>([])
|
|
13
|
+
|
|
14
|
+
function updateSidebar() {
|
|
11
15
|
const sidebarConfig = theme.value.sidebar
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
const relativePath = page.value?.relativePath ?? '/'
|
|
17
|
+
const nextSidebar = resolveSidebar(sidebarConfig, relativePath)
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
if (JSON.stringify(nextSidebar) !== JSON.stringify(sidebar.value))
|
|
20
|
+
sidebar.value = nextSidebar
|
|
21
|
+
}
|
|
16
22
|
|
|
17
|
-
watch(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
watch(
|
|
24
|
+
() => [page.value?.relativePath, theme.value.sidebar],
|
|
25
|
+
() => updateSidebar(),
|
|
26
|
+
{ immediate: true, deep: true, flush: 'sync' },
|
|
27
|
+
)
|
|
21
28
|
|
|
22
29
|
const hasSidebar = computed(() => {
|
|
23
30
|
return (
|
|
@@ -28,9 +35,9 @@ export function useSidebar() {
|
|
|
28
35
|
})
|
|
29
36
|
|
|
30
37
|
const hasAside = computed(() => {
|
|
31
|
-
if (NOT_ARTICLE_LAYOUTS.includes(frontmatter.value.layout))
|
|
38
|
+
if (NOT_ARTICLE_LAYOUTS.includes(frontmatter.value.layout))
|
|
32
39
|
return false
|
|
33
|
-
|
|
40
|
+
|
|
34
41
|
if (frontmatter.value.aside !== undefined && frontmatter.value.aside !== null)
|
|
35
42
|
return !!frontmatter.value.aside
|
|
36
43
|
|
|
@@ -38,18 +45,18 @@ export function useSidebar() {
|
|
|
38
45
|
})
|
|
39
46
|
|
|
40
47
|
const leftAside = computed(() => {
|
|
41
|
-
if (hasAside)
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
if (!hasAside.value)
|
|
49
|
+
return false
|
|
50
|
+
|
|
51
|
+
return frontmatter.value.aside === null
|
|
52
|
+
? theme.value.aside === 'left'
|
|
53
|
+
: frontmatter.value.aside === 'left'
|
|
47
54
|
})
|
|
48
55
|
|
|
49
56
|
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value)
|
|
50
57
|
|
|
51
58
|
const sidebarGroups = computed(() => {
|
|
52
|
-
return hasSidebar.value
|
|
59
|
+
return hasSidebar.value ? groupSidebarItems(sidebar.value) : []
|
|
53
60
|
})
|
|
54
61
|
|
|
55
62
|
function open() {
|
|
@@ -103,3 +110,71 @@ export function useCloseSidebarOnEscape() {
|
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
}
|
|
113
|
+
|
|
114
|
+
function resolveSidebar(
|
|
115
|
+
sidebarConfig: DefaultTheme.Sidebar | undefined,
|
|
116
|
+
relativePath: string,
|
|
117
|
+
): DefaultTheme.SidebarItem[] {
|
|
118
|
+
if (!sidebarConfig)
|
|
119
|
+
return []
|
|
120
|
+
|
|
121
|
+
if (Array.isArray(sidebarConfig))
|
|
122
|
+
return withBase(sidebarConfig)
|
|
123
|
+
|
|
124
|
+
const normalizedPath = ensureStartingSlash(relativePath)
|
|
125
|
+
const matchingDir = Object.keys(sidebarConfig)
|
|
126
|
+
.sort((a, b) => b.split('/').length - a.split('/').length)
|
|
127
|
+
.find(dir => normalizedPath.startsWith(ensureStartingSlash(dir)))
|
|
128
|
+
|
|
129
|
+
const matched = matchingDir ? sidebarConfig[matchingDir] : []
|
|
130
|
+
|
|
131
|
+
if (Array.isArray(matched))
|
|
132
|
+
return withBase(matched)
|
|
133
|
+
|
|
134
|
+
return withBase(matched?.items ?? [], matched?.base)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function withBase(
|
|
138
|
+
items: DefaultTheme.SidebarItem[],
|
|
139
|
+
base?: string,
|
|
140
|
+
): DefaultTheme.SidebarItem[] {
|
|
141
|
+
return items.map((_item) => {
|
|
142
|
+
const item: DefaultTheme.SidebarItem = { ..._item }
|
|
143
|
+
const resolvedBase = item.base || base
|
|
144
|
+
|
|
145
|
+
if (resolvedBase && item.link) {
|
|
146
|
+
item.link = resolvedBase
|
|
147
|
+
+ item.link.replace(/^\//, resolvedBase.endsWith('/') ? '' : '/')
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (item.items)
|
|
151
|
+
item.items = withBase(item.items, resolvedBase)
|
|
152
|
+
|
|
153
|
+
return item
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function groupSidebarItems(
|
|
158
|
+
sidebarItems: DefaultTheme.SidebarItem[],
|
|
159
|
+
): DefaultTheme.SidebarItem[] {
|
|
160
|
+
const groups: DefaultTheme.SidebarItem[] = []
|
|
161
|
+
let lastGroupIndex = 0
|
|
162
|
+
|
|
163
|
+
sidebarItems.forEach((item) => {
|
|
164
|
+
if (item.items && item.items.length) {
|
|
165
|
+
lastGroupIndex = groups.push(item)
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!groups[lastGroupIndex])
|
|
170
|
+
groups.push({ items: [] })
|
|
171
|
+
|
|
172
|
+
const group = groups[lastGroupIndex]
|
|
173
|
+
if (!group.items)
|
|
174
|
+
group.items = []
|
|
175
|
+
|
|
176
|
+
group.items.push(item)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
return groups
|
|
180
|
+
}
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
import type { DefaultTheme } from 'vitepress'
|
|
2
|
-
import type { ComputedRef, Ref } from 'vue'
|
|
3
|
-
import { useData } from 'vitepress'
|
|
4
|
-
import { computed, onMounted, ref, watch, watchEffect, watchPostEffect } from 'vue'
|
|
5
|
-
import { hasActiveLink as containsActiveLink } from '../utils/client/common'
|
|
6
|
-
|
|
7
|
-
import { isActive } from '../utils/common'
|
|
8
|
-
|
|
9
|
-
export interface SidebarControl {
|
|
10
|
-
collapsed: Ref<boolean>
|
|
11
|
-
collapsible: ComputedRef<boolean>
|
|
12
|
-
isLink: ComputedRef<boolean>
|
|
13
|
-
isActiveLink: Ref<boolean>
|
|
14
|
-
hasActiveLink: ComputedRef<boolean>
|
|
15
|
-
hasChildren: ComputedRef<boolean>
|
|
16
|
-
toggle: () => void
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function useSidebarControl(
|
|
20
|
-
item: ComputedRef<DefaultTheme.SidebarItem>,
|
|
21
|
-
): SidebarControl {
|
|
22
|
-
const { page, hash } = useData()
|
|
23
|
-
const collapsed = ref(false)
|
|
24
|
-
|
|
25
|
-
const collapsible = computed(() => {
|
|
26
|
-
return item.value.collapsed !== undefined
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const isLink = computed(() => {
|
|
30
|
-
return !!item.value.link
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
const isActiveLink = ref(false)
|
|
34
|
-
const updateIsActiveLink = () => {
|
|
35
|
-
isActiveLink.value = isActive(page.value.relativePath, item.value.link)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
watch([page, item, hash], updateIsActiveLink)
|
|
39
|
-
onMounted(updateIsActiveLink)
|
|
40
|
-
|
|
41
|
-
const hasActiveLink = computed(() => {
|
|
42
|
-
if (isActiveLink.value) {
|
|
43
|
-
return true
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return item.value.items
|
|
47
|
-
? containsActiveLink(page.value.relativePath, item.value.items)
|
|
48
|
-
: false
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const hasChildren = computed(() => {
|
|
52
|
-
return !!(item.value.items && item.value.items.length)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
watchEffect(() => {
|
|
56
|
-
collapsed.value = !!(collapsible.value && item.value.collapsed)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
watchPostEffect(() => {
|
|
60
|
-
;(isActiveLink.value || hasActiveLink.value) && (collapsed.value = false)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
function toggle() {
|
|
64
|
-
if (collapsible.value) {
|
|
65
|
-
collapsed.value = !collapsed.value
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
collapsed,
|
|
71
|
-
collapsible,
|
|
72
|
-
isLink,
|
|
73
|
-
isActiveLink,
|
|
74
|
-
hasActiveLink,
|
|
75
|
-
hasChildren,
|
|
76
|
-
toggle,
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
import type { DefaultTheme } from 'vitepress'
|
|
2
|
+
import type { ComputedRef, Ref } from 'vue'
|
|
3
|
+
import { useData } from 'vitepress'
|
|
4
|
+
import { computed, onMounted, ref, watch, watchEffect, watchPostEffect } from 'vue'
|
|
5
|
+
import { hasActiveLink as containsActiveLink } from '../utils/client/common'
|
|
6
|
+
|
|
7
|
+
import { isActive } from '../utils/common'
|
|
8
|
+
|
|
9
|
+
export interface SidebarControl {
|
|
10
|
+
collapsed: Ref<boolean>
|
|
11
|
+
collapsible: ComputedRef<boolean>
|
|
12
|
+
isLink: ComputedRef<boolean>
|
|
13
|
+
isActiveLink: Ref<boolean>
|
|
14
|
+
hasActiveLink: ComputedRef<boolean>
|
|
15
|
+
hasChildren: ComputedRef<boolean>
|
|
16
|
+
toggle: () => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useSidebarControl(
|
|
20
|
+
item: ComputedRef<DefaultTheme.SidebarItem>,
|
|
21
|
+
): SidebarControl {
|
|
22
|
+
const { page, hash } = useData()
|
|
23
|
+
const collapsed = ref(false)
|
|
24
|
+
|
|
25
|
+
const collapsible = computed(() => {
|
|
26
|
+
return item.value.collapsed !== undefined
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const isLink = computed(() => {
|
|
30
|
+
return !!item.value.link
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const isActiveLink = ref(false)
|
|
34
|
+
const updateIsActiveLink = () => {
|
|
35
|
+
isActiveLink.value = isActive(page.value.relativePath, item.value.link)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
watch([page, item, hash], updateIsActiveLink)
|
|
39
|
+
onMounted(updateIsActiveLink)
|
|
40
|
+
|
|
41
|
+
const hasActiveLink = computed(() => {
|
|
42
|
+
if (isActiveLink.value) {
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return item.value.items
|
|
47
|
+
? containsActiveLink(page.value.relativePath, item.value.items)
|
|
48
|
+
: false
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const hasChildren = computed(() => {
|
|
52
|
+
return !!(item.value.items && item.value.items.length)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
watchEffect(() => {
|
|
56
|
+
collapsed.value = !!(collapsible.value && item.value.collapsed)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
watchPostEffect(() => {
|
|
60
|
+
;(isActiveLink.value || hasActiveLink.value) && (collapsed.value = false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
function toggle() {
|
|
64
|
+
if (collapsible.value) {
|
|
65
|
+
collapsed.value = !collapsed.value
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
collapsed,
|
|
71
|
+
collapsible,
|
|
72
|
+
isLink,
|
|
73
|
+
isActiveLink,
|
|
74
|
+
hasActiveLink,
|
|
75
|
+
hasChildren,
|
|
76
|
+
toggle,
|
|
77
|
+
}
|
|
78
|
+
}
|