vitepress-theme-element-plus 1.3.1 → 1.3.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/LICENSE +21 -21
- 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 -148
- package/client/components/DeprecatedTag.vue +19 -19
- package/client/components/Doc.vue +185 -185
- package/client/components/DocAside.vue +46 -46
- package/client/components/DocAsideOutline.vue +145 -145
- package/client/components/DocFooter.vue +162 -162
- package/client/components/Footer.vue +100 -100
- 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 +89 -89
- package/client/components/Sidebar.vue +129 -129
- package/client/components/SidebarGroup.vue +51 -51
- package/client/components/SidebarItem.vue +304 -304
- package/client/components/ThemeToggler.vue +129 -129
- package/client/components/VPNavBarSearch.vue +23 -23
- package/client/hooks/useBackTop.ts +71 -71
- package/client/hooks/useLangs.ts +50 -50
- package/client/hooks/useSidebarControl.ts +78 -78
- package/client/hooks/useSize.ts +69 -69
- package/client/icons/dark.vue +8 -8
- package/client/icons/light.vue +8 -8
- package/client/utils/client/common.ts +49 -49
- package/client/utils/client/outline.ts +116 -116
- package/client/utils/common.ts +90 -90
- package/index.ts +45 -45
- package/package.json +2 -2
- package/shared/constants.ts +3 -3
- package/styles/base.scss +105 -105
- package/styles/code.scss +290 -290
- package/styles/doc-content.scss +363 -363
- package/styles/index.scss +71 -71
- package/styles/tag-content.scss +30 -30
|
@@ -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
|
+
}
|
package/client/hooks/useSize.ts
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import type { MaybeRef } from '@vueuse/core'
|
|
2
|
-
import type { Ref, ShallowRef } from 'vue'
|
|
3
|
-
import { useEventListener } from '@vueuse/core'
|
|
4
|
-
import { computed, isRef, onMounted, ref, shallowRef, unref, watch } from 'vue'
|
|
5
|
-
import { isString } from '../utils/common'
|
|
6
|
-
|
|
7
|
-
function getValue(value: string | number): string {
|
|
8
|
-
return isString(value) ? value : `${value}px`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface SizeOptions {
|
|
12
|
-
width: string | number | undefined
|
|
13
|
-
height: string | number | undefined
|
|
14
|
-
ratio: string | number | undefined
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface SizeInfo<E extends HTMLElement> {
|
|
18
|
-
el: ShallowRef<E | undefined>
|
|
19
|
-
width: Ref<string>
|
|
20
|
-
height: Ref<string>
|
|
21
|
-
resize: () => void
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function useSize<E extends HTMLElement>(options: SizeOptions, extraHeight: MaybeRef<number> = 0): SizeInfo<E> {
|
|
25
|
-
const el = shallowRef<E>()
|
|
26
|
-
const width = computed(() => getValue(unref(options.width) ?? '100%'))
|
|
27
|
-
const height = ref('auto')
|
|
28
|
-
|
|
29
|
-
const getRadio = (ratio: number | string | undefined): number => {
|
|
30
|
-
if (isString(ratio)) {
|
|
31
|
-
const [width, height] = ratio.split(':')
|
|
32
|
-
const parsedRadio = Number(width) / Number(height)
|
|
33
|
-
|
|
34
|
-
if (!Number.isNaN(parsedRadio))
|
|
35
|
-
return parsedRadio
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return typeof ratio === 'number' ? ratio : 16 / 9
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const getHeight = (width: number): string => {
|
|
42
|
-
const height = unref(options.height)
|
|
43
|
-
const ratio = getRadio(unref(options.ratio))
|
|
44
|
-
|
|
45
|
-
return height
|
|
46
|
-
? getValue(height)
|
|
47
|
-
: `${Number(width) / ratio + unref(extraHeight)}px`
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const updateHeight = (): void => {
|
|
51
|
-
if (el.value)
|
|
52
|
-
height.value = getHeight(el.value.clientWidth)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
onMounted(() => {
|
|
56
|
-
updateHeight()
|
|
57
|
-
if (isRef(extraHeight))
|
|
58
|
-
watch(extraHeight, updateHeight)
|
|
59
|
-
useEventListener('orientationchange', updateHeight)
|
|
60
|
-
useEventListener('resize', updateHeight)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
el,
|
|
65
|
-
width,
|
|
66
|
-
height,
|
|
67
|
-
resize: updateHeight,
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
import type { MaybeRef } from '@vueuse/core'
|
|
2
|
+
import type { Ref, ShallowRef } from 'vue'
|
|
3
|
+
import { useEventListener } from '@vueuse/core'
|
|
4
|
+
import { computed, isRef, onMounted, ref, shallowRef, unref, watch } from 'vue'
|
|
5
|
+
import { isString } from '../utils/common'
|
|
6
|
+
|
|
7
|
+
function getValue(value: string | number): string {
|
|
8
|
+
return isString(value) ? value : `${value}px`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SizeOptions {
|
|
12
|
+
width: string | number | undefined
|
|
13
|
+
height: string | number | undefined
|
|
14
|
+
ratio: string | number | undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SizeInfo<E extends HTMLElement> {
|
|
18
|
+
el: ShallowRef<E | undefined>
|
|
19
|
+
width: Ref<string>
|
|
20
|
+
height: Ref<string>
|
|
21
|
+
resize: () => void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useSize<E extends HTMLElement>(options: SizeOptions, extraHeight: MaybeRef<number> = 0): SizeInfo<E> {
|
|
25
|
+
const el = shallowRef<E>()
|
|
26
|
+
const width = computed(() => getValue(unref(options.width) ?? '100%'))
|
|
27
|
+
const height = ref('auto')
|
|
28
|
+
|
|
29
|
+
const getRadio = (ratio: number | string | undefined): number => {
|
|
30
|
+
if (isString(ratio)) {
|
|
31
|
+
const [width, height] = ratio.split(':')
|
|
32
|
+
const parsedRadio = Number(width) / Number(height)
|
|
33
|
+
|
|
34
|
+
if (!Number.isNaN(parsedRadio))
|
|
35
|
+
return parsedRadio
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return typeof ratio === 'number' ? ratio : 16 / 9
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const getHeight = (width: number): string => {
|
|
42
|
+
const height = unref(options.height)
|
|
43
|
+
const ratio = getRadio(unref(options.ratio))
|
|
44
|
+
|
|
45
|
+
return height
|
|
46
|
+
? getValue(height)
|
|
47
|
+
: `${Number(width) / ratio + unref(extraHeight)}px`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const updateHeight = (): void => {
|
|
51
|
+
if (el.value)
|
|
52
|
+
height.value = getHeight(el.value.clientWidth)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onMounted(() => {
|
|
56
|
+
updateHeight()
|
|
57
|
+
if (isRef(extraHeight))
|
|
58
|
+
watch(extraHeight, updateHeight)
|
|
59
|
+
useEventListener('orientationchange', updateHeight)
|
|
60
|
+
useEventListener('resize', updateHeight)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
el,
|
|
65
|
+
width,
|
|
66
|
+
height,
|
|
67
|
+
resize: updateHeight,
|
|
68
|
+
}
|
|
69
|
+
}
|
package/client/icons/dark.vue
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<svg viewBox="0 0 24 24" class="dark-icon">
|
|
3
|
-
<path
|
|
4
|
-
d="M11.01 3.05C6.51 3.54 3 7.36 3 12a9 9 0 0 0 9 9c4.63 0 8.45-3.5 8.95-8c.09-.79-.78-1.42-1.54-.95A5.403 5.403 0 0 1 11.1 7.5c0-1.06.31-2.06.84-2.89c.45-.67-.04-1.63-.93-1.56z"
|
|
5
|
-
fill="currentColor"
|
|
6
|
-
/>
|
|
7
|
-
</svg>
|
|
8
|
-
</template>
|
|
1
|
+
<template>
|
|
2
|
+
<svg viewBox="0 0 24 24" class="dark-icon">
|
|
3
|
+
<path
|
|
4
|
+
d="M11.01 3.05C6.51 3.54 3 7.36 3 12a9 9 0 0 0 9 9c4.63 0 8.45-3.5 8.95-8c.09-.79-.78-1.42-1.54-.95A5.403 5.403 0 0 1 11.1 7.5c0-1.06.31-2.06.84-2.89c.45-.67-.04-1.63-.93-1.56z"
|
|
5
|
+
fill="currentColor"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
8
|
+
</template>
|
package/client/icons/light.vue
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<svg viewBox="0 0 24 24" class="light-icon">
|
|
3
|
-
<path
|
|
4
|
-
d="M6.05 4.14l-.39-.39a.993.993 0 0 0-1.4 0l-.01.01a.984.984 0 0 0 0 1.4l.39.39c.39.39 1.01.39 1.4 0l.01-.01a.984.984 0 0 0 0-1.4zM3.01 10.5H1.99c-.55 0-.99.44-.99.99v.01c0 .55.44.99.99.99H3c.56.01 1-.43 1-.98v-.01c0-.56-.44-1-.99-1zm9-9.95H12c-.56 0-1 .44-1 .99v.96c0 .55.44.99.99.99H12c.56.01 1-.43 1-.98v-.97c0-.55-.44-.99-.99-.99zm7.74 3.21c-.39-.39-1.02-.39-1.41-.01l-.39.39a.984.984 0 0 0 0 1.4l.01.01c.39.39 1.02.39 1.4 0l.39-.39a.984.984 0 0 0 0-1.4zm-1.81 15.1l.39.39a.996.996 0 1 0 1.41-1.41l-.39-.39a.993.993 0 0 0-1.4 0c-.4.4-.4 1.02-.01 1.41zM20 11.49v.01c0 .55.44.99.99.99H22c.55 0 .99-.44.99-.99v-.01c0-.55-.44-.99-.99-.99h-1.01c-.55 0-.99.44-.99.99zM12 5.5c-3.31 0-6 2.69-6 6s2.69 6 6 6s6-2.69 6-6s-2.69-6-6-6zm-.01 16.95H12c.55 0 .99-.44.99-.99v-.96c0-.55-.44-.99-.99-.99h-.01c-.55 0-.99.44-.99.99v.96c0 .55.44.99.99.99zm-7.74-3.21c.39.39 1.02.39 1.41 0l.39-.39a.993.993 0 0 0 0-1.4l-.01-.01a.996.996 0 0 0-1.41 0l-.39.39c-.38.4-.38 1.02.01 1.41z"
|
|
5
|
-
fill="currentColor"
|
|
6
|
-
/>
|
|
7
|
-
</svg>
|
|
8
|
-
</template>
|
|
1
|
+
<template>
|
|
2
|
+
<svg viewBox="0 0 24 24" class="light-icon">
|
|
3
|
+
<path
|
|
4
|
+
d="M6.05 4.14l-.39-.39a.993.993 0 0 0-1.4 0l-.01.01a.984.984 0 0 0 0 1.4l.39.39c.39.39 1.01.39 1.4 0l.01-.01a.984.984 0 0 0 0-1.4zM3.01 10.5H1.99c-.55 0-.99.44-.99.99v.01c0 .55.44.99.99.99H3c.56.01 1-.43 1-.98v-.01c0-.56-.44-1-.99-1zm9-9.95H12c-.56 0-1 .44-1 .99v.96c0 .55.44.99.99.99H12c.56.01 1-.43 1-.98v-.97c0-.55-.44-.99-.99-.99zm7.74 3.21c-.39-.39-1.02-.39-1.41-.01l-.39.39a.984.984 0 0 0 0 1.4l.01.01c.39.39 1.02.39 1.4 0l.39-.39a.984.984 0 0 0 0-1.4zm-1.81 15.1l.39.39a.996.996 0 1 0 1.41-1.41l-.39-.39a.993.993 0 0 0-1.4 0c-.4.4-.4 1.02-.01 1.41zM20 11.49v.01c0 .55.44.99.99.99H22c.55 0 .99-.44.99-.99v-.01c0-.55-.44-.99-.99-.99h-1.01c-.55 0-.99.44-.99.99zM12 5.5c-3.31 0-6 2.69-6 6s2.69 6 6 6s6-2.69 6-6s-2.69-6-6-6zm-.01 16.95H12c.55 0 .99-.44.99-.99v-.96c0-.55-.44-.99-.99-.99h-.01c-.55 0-.99.44-.99.99v.96c0 .55.44.99.99.99zm-7.74-3.21c.39.39 1.02.39 1.41 0l.39-.39a.993.993 0 0 0 0-1.4l-.01-.01a.996.996 0 0 0-1.41 0l-.39.39c-.38.4-.38 1.02.01 1.41z"
|
|
5
|
+
fill="currentColor"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
8
|
+
</template>
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import type { DefaultTheme } from 'vitepress'
|
|
2
|
-
import { isActive } from '../common'
|
|
3
|
-
|
|
4
|
-
export interface SidebarLink {
|
|
5
|
-
text: string
|
|
6
|
-
link: string
|
|
7
|
-
docFooterText?: string
|
|
8
|
-
}
|
|
9
|
-
export function getFlatSideBarLinks(sidebar: DefaultTheme.SidebarItem[]): SidebarLink[] {
|
|
10
|
-
const links: SidebarLink[] = []
|
|
11
|
-
|
|
12
|
-
function recursivelyExtractLinks(items: DefaultTheme.SidebarItem[]) {
|
|
13
|
-
for (const item of items) {
|
|
14
|
-
if (item.text && item.link) {
|
|
15
|
-
links.push({
|
|
16
|
-
text: item.text,
|
|
17
|
-
link: item.link,
|
|
18
|
-
docFooterText: item.docFooterText,
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (item.items) {
|
|
23
|
-
recursivelyExtractLinks(item.items)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
recursivelyExtractLinks(sidebar)
|
|
29
|
-
|
|
30
|
-
return links
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Check if the given sidebar item contains any active link.
|
|
35
|
-
*/
|
|
36
|
-
export function hasActiveLink(
|
|
37
|
-
path: string,
|
|
38
|
-
items: DefaultTheme.SidebarItem | DefaultTheme.SidebarItem[],
|
|
39
|
-
): boolean {
|
|
40
|
-
if (Array.isArray(items)) {
|
|
41
|
-
return items.some(item => hasActiveLink(path, item))
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return isActive(path, items.link)
|
|
45
|
-
? true
|
|
46
|
-
: items.items
|
|
47
|
-
? hasActiveLink(path, items.items)
|
|
48
|
-
: false
|
|
49
|
-
}
|
|
1
|
+
import type { DefaultTheme } from 'vitepress'
|
|
2
|
+
import { isActive } from '../common'
|
|
3
|
+
|
|
4
|
+
export interface SidebarLink {
|
|
5
|
+
text: string
|
|
6
|
+
link: string
|
|
7
|
+
docFooterText?: string
|
|
8
|
+
}
|
|
9
|
+
export function getFlatSideBarLinks(sidebar: DefaultTheme.SidebarItem[]): SidebarLink[] {
|
|
10
|
+
const links: SidebarLink[] = []
|
|
11
|
+
|
|
12
|
+
function recursivelyExtractLinks(items: DefaultTheme.SidebarItem[]) {
|
|
13
|
+
for (const item of items) {
|
|
14
|
+
if (item.text && item.link) {
|
|
15
|
+
links.push({
|
|
16
|
+
text: item.text,
|
|
17
|
+
link: item.link,
|
|
18
|
+
docFooterText: item.docFooterText,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (item.items) {
|
|
23
|
+
recursivelyExtractLinks(item.items)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
recursivelyExtractLinks(sidebar)
|
|
29
|
+
|
|
30
|
+
return links
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if the given sidebar item contains any active link.
|
|
35
|
+
*/
|
|
36
|
+
export function hasActiveLink(
|
|
37
|
+
path: string,
|
|
38
|
+
items: DefaultTheme.SidebarItem | DefaultTheme.SidebarItem[],
|
|
39
|
+
): boolean {
|
|
40
|
+
if (Array.isArray(items)) {
|
|
41
|
+
return items.some(item => hasActiveLink(path, item))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return isActive(path, items.link)
|
|
45
|
+
? true
|
|
46
|
+
: items.items
|
|
47
|
+
? hasActiveLink(path, items.items)
|
|
48
|
+
: false
|
|
49
|
+
}
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import type { Header } from 'vitepress'
|
|
2
|
-
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
-
|
|
4
|
-
const ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/
|
|
5
|
-
|
|
6
|
-
// cached list of anchor elements from resolveHeaders
|
|
7
|
-
const resolvedHeaders: { element: HTMLHeadElement, link: string }[] = []
|
|
8
|
-
|
|
9
|
-
export type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
|
10
|
-
element: HTMLHeadElement
|
|
11
|
-
titleTags: string[]
|
|
12
|
-
children?: MenuItem[]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function resolveTitle(theme: DefaultTheme.Config): string {
|
|
16
|
-
return (
|
|
17
|
-
(typeof theme.outline === 'object'
|
|
18
|
-
&& !Array.isArray(theme.outline)
|
|
19
|
-
&& theme.outline.label)
|
|
20
|
-
|| theme.outlineTitle
|
|
21
|
-
|| 'On this page'
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
|
|
26
|
-
const headers = Array.from(document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'))
|
|
27
|
-
.filter(el => el.id && el.hasChildNodes())
|
|
28
|
-
.map((el) => {
|
|
29
|
-
const level = Number(el.tagName[1])
|
|
30
|
-
const { text, tags } = serializeHeader(el)
|
|
31
|
-
return {
|
|
32
|
-
element: el as HTMLHeadElement,
|
|
33
|
-
title: text,
|
|
34
|
-
titleTags: tags,
|
|
35
|
-
link: `#${el.id}`,
|
|
36
|
-
level,
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
return resolveHeaders(headers, range)
|
|
41
|
-
}
|
|
42
|
-
|
|
1
|
+
import type { Header } from 'vitepress'
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
+
|
|
4
|
+
const ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/
|
|
5
|
+
|
|
6
|
+
// cached list of anchor elements from resolveHeaders
|
|
7
|
+
const resolvedHeaders: { element: HTMLHeadElement, link: string }[] = []
|
|
8
|
+
|
|
9
|
+
export type MenuItem = Omit<Header, 'slug' | 'children'> & {
|
|
10
|
+
element: HTMLHeadElement
|
|
11
|
+
titleTags: string[]
|
|
12
|
+
children?: MenuItem[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function resolveTitle(theme: DefaultTheme.Config): string {
|
|
16
|
+
return (
|
|
17
|
+
(typeof theme.outline === 'object'
|
|
18
|
+
&& !Array.isArray(theme.outline)
|
|
19
|
+
&& theme.outline.label)
|
|
20
|
+
|| theme.outlineTitle
|
|
21
|
+
|| 'On this page'
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
|
|
26
|
+
const headers = Array.from(document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)'))
|
|
27
|
+
.filter(el => el.id && el.hasChildNodes())
|
|
28
|
+
.map((el) => {
|
|
29
|
+
const level = Number(el.tagName[1])
|
|
30
|
+
const { text, tags } = serializeHeader(el)
|
|
31
|
+
return {
|
|
32
|
+
element: el as HTMLHeadElement,
|
|
33
|
+
title: text,
|
|
34
|
+
titleTags: tags,
|
|
35
|
+
link: `#${el.id}`,
|
|
36
|
+
level,
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return resolveHeaders(headers, range)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
43
|
function serializeHeader(h: Element): { text: string, tags: string[] } {
|
|
44
44
|
let text = ''
|
|
45
45
|
const tags: string[] = []
|
|
46
46
|
for (const node of Array.from(h.childNodes)) {
|
|
47
47
|
if (node.nodeType === 1) {
|
|
48
48
|
const element = node as HTMLElement
|
|
49
|
-
if (ignoreRE.test(element.className))
|
|
50
|
-
continue
|
|
49
|
+
if (ignoreRE.test(element.className))
|
|
50
|
+
continue
|
|
51
51
|
if (element.classList.contains('el-tag') || element.classList.contains('vp-tag')) {
|
|
52
52
|
const cloned = element.cloneNode(true) as HTMLElement
|
|
53
53
|
const transitionClassRE = /(?:^|-)enter-(?:active|from|to)$|(?:^|-)leave-(?:active|from|to)$/
|
|
@@ -59,75 +59,75 @@ function serializeHeader(h: Element): { text: string, tags: string[] } {
|
|
|
59
59
|
tags.push(cloned.outerHTML)
|
|
60
60
|
continue
|
|
61
61
|
}
|
|
62
|
-
text += element.textContent ?? ''
|
|
63
|
-
}
|
|
64
|
-
else if (node.nodeType === 3) {
|
|
65
|
-
const value = node.textContent ?? ''
|
|
66
|
-
text += value
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
text: text.trim(),
|
|
71
|
-
tags,
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function resolveHeaders(
|
|
76
|
-
headers: MenuItem[],
|
|
77
|
-
range?: DefaultTheme.Config['outline'],
|
|
78
|
-
): MenuItem[] {
|
|
79
|
-
if (range === false) {
|
|
80
|
-
return []
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const levelsRange
|
|
84
|
-
= (typeof range === 'object' && !Array.isArray(range)
|
|
85
|
-
? range.level
|
|
86
|
-
: range) || 2
|
|
87
|
-
|
|
88
|
-
const [high, low]: [number, number]
|
|
89
|
-
= typeof levelsRange === 'number'
|
|
90
|
-
? [levelsRange, levelsRange]
|
|
91
|
-
: levelsRange === 'deep'
|
|
92
|
-
? [2, 6]
|
|
93
|
-
: levelsRange
|
|
94
|
-
|
|
95
|
-
return buildTree(headers, high, low)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
|
|
99
|
-
resolvedHeaders.length = 0
|
|
100
|
-
|
|
101
|
-
const result: MenuItem[] = []
|
|
102
|
-
const stack: (MenuItem | { level: number, shouldIgnore: true })[] = []
|
|
103
|
-
|
|
104
|
-
data.forEach((item) => {
|
|
105
|
-
const node = { ...item, children: [] }
|
|
106
|
-
let parent = stack[stack.length - 1]
|
|
107
|
-
|
|
108
|
-
while (parent && parent.level >= node.level) {
|
|
109
|
-
stack.pop()
|
|
110
|
-
parent = stack[stack.length - 1]
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
node.element.classList.contains('ignore-header')
|
|
115
|
-
|| (parent && 'shouldIgnore' in parent)
|
|
116
|
-
) {
|
|
117
|
-
stack.push({ level: node.level, shouldIgnore: true })
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (node.level > max || node.level < min)
|
|
122
|
-
return
|
|
123
|
-
resolvedHeaders.push({ element: node.element, link: node.link })
|
|
124
|
-
|
|
125
|
-
if (parent)
|
|
126
|
-
(parent as MenuItem).children.push(node)
|
|
127
|
-
else result.push(node)
|
|
128
|
-
|
|
129
|
-
stack.push(node)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
return result
|
|
133
|
-
}
|
|
62
|
+
text += element.textContent ?? ''
|
|
63
|
+
}
|
|
64
|
+
else if (node.nodeType === 3) {
|
|
65
|
+
const value = node.textContent ?? ''
|
|
66
|
+
text += value
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
text: text.trim(),
|
|
71
|
+
tags,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function resolveHeaders(
|
|
76
|
+
headers: MenuItem[],
|
|
77
|
+
range?: DefaultTheme.Config['outline'],
|
|
78
|
+
): MenuItem[] {
|
|
79
|
+
if (range === false) {
|
|
80
|
+
return []
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const levelsRange
|
|
84
|
+
= (typeof range === 'object' && !Array.isArray(range)
|
|
85
|
+
? range.level
|
|
86
|
+
: range) || 2
|
|
87
|
+
|
|
88
|
+
const [high, low]: [number, number]
|
|
89
|
+
= typeof levelsRange === 'number'
|
|
90
|
+
? [levelsRange, levelsRange]
|
|
91
|
+
: levelsRange === 'deep'
|
|
92
|
+
? [2, 6]
|
|
93
|
+
: levelsRange
|
|
94
|
+
|
|
95
|
+
return buildTree(headers, high, low)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
|
|
99
|
+
resolvedHeaders.length = 0
|
|
100
|
+
|
|
101
|
+
const result: MenuItem[] = []
|
|
102
|
+
const stack: (MenuItem | { level: number, shouldIgnore: true })[] = []
|
|
103
|
+
|
|
104
|
+
data.forEach((item) => {
|
|
105
|
+
const node = { ...item, children: [] }
|
|
106
|
+
let parent = stack[stack.length - 1]
|
|
107
|
+
|
|
108
|
+
while (parent && parent.level >= node.level) {
|
|
109
|
+
stack.pop()
|
|
110
|
+
parent = stack[stack.length - 1]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
node.element.classList.contains('ignore-header')
|
|
115
|
+
|| (parent && 'shouldIgnore' in parent)
|
|
116
|
+
) {
|
|
117
|
+
stack.push({ level: node.level, shouldIgnore: true })
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (node.level > max || node.level < min)
|
|
122
|
+
return
|
|
123
|
+
resolvedHeaders.push({ element: node.element, link: node.link })
|
|
124
|
+
|
|
125
|
+
if (parent)
|
|
126
|
+
(parent as MenuItem).children.push(node)
|
|
127
|
+
else result.push(node)
|
|
128
|
+
|
|
129
|
+
stack.push(node)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
return result
|
|
133
|
+
}
|