vitepress 1.2.2 → 1.3.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/dist/client/app/data.js +1 -1
- package/dist/client/app/router.js +41 -40
- package/dist/client/theme-default/components/VPDocFooter.vue +29 -13
- package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +2 -2
- package/dist/client/theme-default/components/VPMenu.vue +7 -2
- package/dist/client/theme-default/components/VPNavBar.vue +10 -3
- package/dist/client/theme-default/components/VPNavBarAppearance.vue +8 -1
- package/dist/client/theme-default/components/VPNavBarExtra.vue +17 -3
- package/dist/client/theme-default/components/VPNavBarMenu.vue +14 -3
- package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +7 -7
- package/dist/client/theme-default/components/VPNavScreen.vue +2 -2
- package/dist/client/theme-default/components/VPNavScreenAppearance.vue +8 -1
- package/dist/client/theme-default/components/VPNavScreenMenu.vue +7 -4
- package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +9 -8
- package/dist/client/theme-default/components/VPSidebar.vue +18 -19
- package/dist/client/theme-default/components/VPSidebarGroup.vue +56 -0
- package/dist/client/theme-default/components/VPSidebarItem.vue +3 -3
- package/dist/client/theme-default/components/VPSwitchAppearance.vue +5 -3
- package/dist/client/theme-default/styles/base.css +1 -2
- package/dist/client/theme-default/styles/components/vp-doc.css +10 -2
- package/dist/client/theme-default/without-fonts.js +1 -0
- package/dist/node/cli.js +20 -14
- package/dist/node/index.d.ts +7 -6
- package/dist/node/index.js +2 -2
- package/dist/node/{serve-BwR5EPUJ.js → serve-BhLFz9dF.js} +713 -395
- package/package.json +41 -44
- package/theme.d.ts +1 -0
- package/types/default-theme.d.ts +9 -4
- package/types/shared.d.ts +1 -0
package/dist/client/app/data.js
CHANGED
|
@@ -22,7 +22,7 @@ export function initData(route) {
|
|
|
22
22
|
: appearance
|
|
23
23
|
? useDark({
|
|
24
24
|
storageKey: APPEARANCE_KEY,
|
|
25
|
-
initialValue: () =>
|
|
25
|
+
initialValue: () => (appearance === 'dark' ? 'dark' : 'auto'),
|
|
26
26
|
...(typeof appearance === 'object' ? appearance : {})
|
|
27
27
|
})
|
|
28
28
|
: ref(false);
|
|
@@ -117,52 +117,53 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
117
117
|
history.replaceState({}, '');
|
|
118
118
|
}
|
|
119
119
|
window.addEventListener('click', (e) => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
if (e.defaultPrevented ||
|
|
121
|
+
!(e.target instanceof Element) ||
|
|
122
|
+
e.target.closest('button') || // temporary fix for docsearch action buttons
|
|
123
|
+
e.button !== 0 ||
|
|
124
|
+
e.ctrlKey ||
|
|
125
|
+
e.shiftKey ||
|
|
126
|
+
e.altKey ||
|
|
127
|
+
e.metaKey)
|
|
123
128
|
return;
|
|
124
129
|
const link = e.target.closest('a');
|
|
125
|
-
if (link
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (hash) {
|
|
155
|
-
// use smooth scroll when clicking on header anchor links
|
|
156
|
-
scrollTo(link, hash, link.classList.contains('header-anchor'));
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
window.scrollTo(0, 0);
|
|
160
|
-
}
|
|
130
|
+
if (!link ||
|
|
131
|
+
link.closest('.vp-raw') ||
|
|
132
|
+
link.hasAttribute('download') ||
|
|
133
|
+
link.hasAttribute('target'))
|
|
134
|
+
return;
|
|
135
|
+
const linkHref = link.getAttribute('href') ??
|
|
136
|
+
(link instanceof SVGAElement ? link.getAttribute('xlink:href') : null);
|
|
137
|
+
if (linkHref == null)
|
|
138
|
+
return;
|
|
139
|
+
const { href, origin, pathname, hash, search } = new URL(linkHref, link.baseURI);
|
|
140
|
+
const currentUrl = new URL(location.href); // copy to keep old data
|
|
141
|
+
// only intercept inbound html links
|
|
142
|
+
if (origin === currentUrl.origin && treatAsHtml(pathname)) {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
if (pathname === currentUrl.pathname &&
|
|
145
|
+
search === currentUrl.search) {
|
|
146
|
+
// scroll between hash anchors in the same page
|
|
147
|
+
// avoid duplicate history entries when the hash is same
|
|
148
|
+
if (hash !== currentUrl.hash) {
|
|
149
|
+
history.pushState({}, '', href);
|
|
150
|
+
// still emit the event so we can listen to it in themes
|
|
151
|
+
window.dispatchEvent(new HashChangeEvent('hashchange', {
|
|
152
|
+
oldURL: currentUrl.href,
|
|
153
|
+
newURL: href
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
if (hash) {
|
|
157
|
+
// use smooth scroll when clicking on header anchor links
|
|
158
|
+
scrollTo(link, hash, link.classList.contains('header-anchor'));
|
|
161
159
|
}
|
|
162
160
|
else {
|
|
163
|
-
|
|
161
|
+
window.scrollTo(0, 0);
|
|
164
162
|
}
|
|
165
163
|
}
|
|
164
|
+
else {
|
|
165
|
+
go(href);
|
|
166
|
+
}
|
|
166
167
|
}
|
|
167
168
|
}, { capture: true });
|
|
168
169
|
window.addEventListener('popstate', async (e) => {
|
|
@@ -11,15 +11,17 @@ const { theme, page, frontmatter } = useData()
|
|
|
11
11
|
const editLink = useEditLink()
|
|
12
12
|
const control = usePrevNext()
|
|
13
13
|
|
|
14
|
-
const hasEditLink = computed(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const hasLastUpdated = computed(() =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const hasEditLink = computed(
|
|
15
|
+
() => theme.value.editLink && frontmatter.value.editLink !== false
|
|
16
|
+
)
|
|
17
|
+
const hasLastUpdated = computed(() => page.value.lastUpdated)
|
|
18
|
+
const showFooter = computed(
|
|
19
|
+
() =>
|
|
20
|
+
hasEditLink.value ||
|
|
21
|
+
hasLastUpdated.value ||
|
|
22
|
+
control.value.prev ||
|
|
23
|
+
control.value.next
|
|
24
|
+
)
|
|
23
25
|
</script>
|
|
24
26
|
|
|
25
27
|
<template>
|
|
@@ -47,14 +49,28 @@ const showFooter = computed(() => {
|
|
|
47
49
|
<span class="visually-hidden" id="doc-footer-aria-label">Pager</span>
|
|
48
50
|
|
|
49
51
|
<div class="pager">
|
|
50
|
-
<VPLink
|
|
51
|
-
|
|
52
|
+
<VPLink
|
|
53
|
+
v-if="control.prev?.link"
|
|
54
|
+
class="pager-link prev"
|
|
55
|
+
:href="control.prev.link"
|
|
56
|
+
>
|
|
57
|
+
<span
|
|
58
|
+
class="desc"
|
|
59
|
+
v-html="theme.docFooter?.prev || 'Previous page'"
|
|
60
|
+
></span>
|
|
52
61
|
<span class="title" v-html="control.prev.text"></span>
|
|
53
62
|
</VPLink>
|
|
54
63
|
</div>
|
|
55
64
|
<div class="pager">
|
|
56
|
-
<VPLink
|
|
57
|
-
|
|
65
|
+
<VPLink
|
|
66
|
+
v-if="control.next?.link"
|
|
67
|
+
class="pager-link next"
|
|
68
|
+
:href="control.next.link"
|
|
69
|
+
>
|
|
70
|
+
<span
|
|
71
|
+
class="desc"
|
|
72
|
+
v-html="theme.docFooter?.next || 'Next page'"
|
|
73
|
+
></span>
|
|
58
74
|
<span class="title" v-html="control.next.text"></span>
|
|
59
75
|
</VPLink>
|
|
60
76
|
</div>
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { ref, computed, watchEffect, onMounted } from 'vue'
|
|
3
3
|
import { useData } from '../composables/data'
|
|
4
4
|
|
|
5
|
-
const { theme, page,
|
|
5
|
+
const { theme, page, lang } = useData()
|
|
6
6
|
|
|
7
7
|
const date = computed(
|
|
8
|
-
() => new Date(
|
|
8
|
+
() => new Date(page.value.lastUpdated!)
|
|
9
9
|
)
|
|
10
10
|
const isoDatetime = computed(() => date.value.toISOString())
|
|
11
11
|
const datetime = ref('')
|
|
@@ -10,8 +10,13 @@ defineProps<{
|
|
|
10
10
|
<template>
|
|
11
11
|
<div class="VPMenu">
|
|
12
12
|
<div v-if="items" class="items">
|
|
13
|
-
<template v-for="item in items" :key="item
|
|
13
|
+
<template v-for="item in items" :key="JSON.stringify(item)">
|
|
14
14
|
<VPMenuLink v-if="'link' in item" :item="item" />
|
|
15
|
+
<component
|
|
16
|
+
v-else-if="'component' in item"
|
|
17
|
+
:is="item.component"
|
|
18
|
+
v-bind="item.props"
|
|
19
|
+
/>
|
|
15
20
|
<VPMenuGroup v-else :text="item.text" :items="item.items" />
|
|
16
21
|
</template>
|
|
17
22
|
</div>
|
|
@@ -63,7 +68,7 @@ defineProps<{
|
|
|
63
68
|
font-size: 12px;
|
|
64
69
|
font-weight: 500;
|
|
65
70
|
color: var(--vp-c-text-2);
|
|
66
|
-
transition: color .5s;
|
|
71
|
+
transition: color 0.5s;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
.VPMenu :deep(.action) {
|
|
@@ -12,7 +12,7 @@ import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
|
|
|
12
12
|
import VPNavBarTitle from './VPNavBarTitle.vue'
|
|
13
13
|
import VPNavBarTranslations from './VPNavBarTranslations.vue'
|
|
14
14
|
|
|
15
|
-
defineProps<{
|
|
15
|
+
const props = defineProps<{
|
|
16
16
|
isScreenOpen: boolean
|
|
17
17
|
}>()
|
|
18
18
|
|
|
@@ -31,6 +31,7 @@ watchPostEffect(() => {
|
|
|
31
31
|
'has-sidebar': hasSidebar.value,
|
|
32
32
|
'home': frontmatter.value.layout === 'home',
|
|
33
33
|
'top': y.value === 0,
|
|
34
|
+
'screen-open': props.isScreenOpen
|
|
34
35
|
}
|
|
35
36
|
})
|
|
36
37
|
</script>
|
|
@@ -74,7 +75,13 @@ watchPostEffect(() => {
|
|
|
74
75
|
height: var(--vp-nav-height);
|
|
75
76
|
pointer-events: none;
|
|
76
77
|
white-space: nowrap;
|
|
77
|
-
transition: background-color 0.
|
|
78
|
+
transition: background-color 0.25s;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.VPNavBar.screen-open {
|
|
82
|
+
transition: none;
|
|
83
|
+
background-color: var(--vp-nav-bg-color);
|
|
84
|
+
border-bottom: 1px solid var(--vp-c-divider);
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
.VPNavBar:not(.home) {
|
|
@@ -255,7 +262,7 @@ watchPostEffect(() => {
|
|
|
255
262
|
background-color: var(--vp-c-gutter);
|
|
256
263
|
}
|
|
257
264
|
|
|
258
|
-
@media (min-width: 960px) {
|
|
265
|
+
@media (min-width: 960px) {
|
|
259
266
|
.VPNavBar:not(.home.top) .divider-line {
|
|
260
267
|
background-color: var(--vp-c-gutter);
|
|
261
268
|
}
|
|
@@ -6,7 +6,14 @@ const { site } = useData()
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<template>
|
|
9
|
-
<div
|
|
9
|
+
<div
|
|
10
|
+
v-if="
|
|
11
|
+
site.appearance &&
|
|
12
|
+
site.appearance !== 'force-dark' &&
|
|
13
|
+
site.appearance !== 'force-auto'
|
|
14
|
+
"
|
|
15
|
+
class="VPNavBarAppearance"
|
|
16
|
+
>
|
|
10
17
|
<VPSwitchAppearance />
|
|
11
18
|
</div>
|
|
12
19
|
</template>
|
|
@@ -19,8 +19,15 @@ const hasExtraContent = computed(
|
|
|
19
19
|
</script>
|
|
20
20
|
|
|
21
21
|
<template>
|
|
22
|
-
<VPFlyout
|
|
23
|
-
|
|
22
|
+
<VPFlyout
|
|
23
|
+
v-if="hasExtraContent"
|
|
24
|
+
class="VPNavBarExtra"
|
|
25
|
+
label="extra navigation"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
v-if="localeLinks.length && currentLang.label"
|
|
29
|
+
class="group translations"
|
|
30
|
+
>
|
|
24
31
|
<p class="trans-title">{{ currentLang.label }}</p>
|
|
25
32
|
|
|
26
33
|
<template v-for="locale in localeLinks" :key="locale.link">
|
|
@@ -28,7 +35,14 @@ const hasExtraContent = computed(
|
|
|
28
35
|
</template>
|
|
29
36
|
</div>
|
|
30
37
|
|
|
31
|
-
<div
|
|
38
|
+
<div
|
|
39
|
+
v-if="
|
|
40
|
+
site.appearance &&
|
|
41
|
+
site.appearance !== 'force-dark' &&
|
|
42
|
+
site.appearance !== 'force-auto'
|
|
43
|
+
"
|
|
44
|
+
class="group"
|
|
45
|
+
>
|
|
32
46
|
<div class="item appearance">
|
|
33
47
|
<p class="label">
|
|
34
48
|
{{ theme.darkModeSwitchLabel || 'Appearance' }}
|
|
@@ -7,10 +7,21 @@ const { theme } = useData()
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
|
-
<nav
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
<nav
|
|
11
|
+
v-if="theme.nav"
|
|
12
|
+
aria-labelledby="main-nav-aria-label"
|
|
13
|
+
class="VPNavBarMenu"
|
|
14
|
+
>
|
|
15
|
+
<span id="main-nav-aria-label" class="visually-hidden">
|
|
16
|
+
Main Navigation
|
|
17
|
+
</span>
|
|
18
|
+
<template v-for="item in theme.nav" :key="JSON.stringify(item)">
|
|
13
19
|
<VPNavBarMenuLink v-if="'link' in item" :item="item" />
|
|
20
|
+
<component
|
|
21
|
+
v-else-if="'component' in item"
|
|
22
|
+
:is="item.component"
|
|
23
|
+
v-bind="item.props"
|
|
24
|
+
/>
|
|
14
25
|
<VPNavBarMenuGroup v-else :item="item" />
|
|
15
26
|
</template>
|
|
16
27
|
</nav>
|
|
@@ -12,15 +12,17 @@ const props = defineProps<{
|
|
|
12
12
|
const { page } = useData()
|
|
13
13
|
|
|
14
14
|
const isChildActive = (navItem: DefaultTheme.NavItem) => {
|
|
15
|
+
if ('component' in navItem) return false
|
|
16
|
+
|
|
15
17
|
if ('link' in navItem) {
|
|
16
18
|
return isActive(
|
|
17
19
|
page.value.relativePath,
|
|
18
20
|
navItem.link,
|
|
19
21
|
!!props.item.activeMatch
|
|
20
22
|
)
|
|
21
|
-
} else {
|
|
22
|
-
return navItem.items.some(isChildActive)
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
return navItem.items.some(isChildActive)
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
const childrenActive = computed(() => isChildActive(props.item))
|
|
@@ -30,11 +32,9 @@ const childrenActive = computed(() => isChildActive(props.item))
|
|
|
30
32
|
<VPFlyout
|
|
31
33
|
:class="{
|
|
32
34
|
VPNavBarMenuGroup: true,
|
|
33
|
-
active:
|
|
34
|
-
page.relativePath,
|
|
35
|
-
|
|
36
|
-
!!item.activeMatch
|
|
37
|
-
) || childrenActive
|
|
35
|
+
active:
|
|
36
|
+
isActive(page.relativePath, item.activeMatch, !!item.activeMatch) ||
|
|
37
|
+
childrenActive
|
|
38
38
|
}"
|
|
39
39
|
:button="item.text"
|
|
40
40
|
:items="item.items"
|
|
@@ -37,7 +37,7 @@ const isLocked = useScrollLock(inBrowser ? document.body : null)
|
|
|
37
37
|
<style scoped>
|
|
38
38
|
.VPNavScreen {
|
|
39
39
|
position: fixed;
|
|
40
|
-
top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px)
|
|
40
|
+
top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));
|
|
41
41
|
/*rtl:ignore*/
|
|
42
42
|
right: 0;
|
|
43
43
|
bottom: 0;
|
|
@@ -47,7 +47,7 @@ const isLocked = useScrollLock(inBrowser ? document.body : null)
|
|
|
47
47
|
width: 100%;
|
|
48
48
|
background-color: var(--vp-nav-screen-bg-color);
|
|
49
49
|
overflow-y: auto;
|
|
50
|
-
transition: background-color 0.
|
|
50
|
+
transition: background-color 0.25s;
|
|
51
51
|
pointer-events: auto;
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -6,7 +6,14 @@ const { site, theme } = useData()
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<template>
|
|
9
|
-
<div
|
|
9
|
+
<div
|
|
10
|
+
v-if="
|
|
11
|
+
site.appearance &&
|
|
12
|
+
site.appearance !== 'force-dark' &&
|
|
13
|
+
site.appearance !== 'force-auto'
|
|
14
|
+
"
|
|
15
|
+
class="VPNavScreenAppearance"
|
|
16
|
+
>
|
|
10
17
|
<p class="text">
|
|
11
18
|
{{ theme.darkModeSwitchLabel || 'Appearance' }}
|
|
12
19
|
</p>
|
|
@@ -8,10 +8,13 @@ const { theme } = useData()
|
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
10
|
<nav v-if="theme.nav" class="VPNavScreenMenu">
|
|
11
|
-
<template v-for="item in theme.nav" :key="item
|
|
12
|
-
<VPNavScreenMenuLink
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
<template v-for="item in theme.nav" :key="JSON.stringify(item)">
|
|
12
|
+
<VPNavScreenMenuLink v-if="'link' in item" :item="item" />
|
|
13
|
+
<component
|
|
14
|
+
v-else-if="'component' in item"
|
|
15
|
+
:is="item.component"
|
|
16
|
+
v-bind="item.props"
|
|
17
|
+
screen-menu
|
|
15
18
|
/>
|
|
16
19
|
<VPNavScreenMenuGroup
|
|
17
20
|
v-else
|
|
@@ -10,8 +10,8 @@ const props = defineProps<{
|
|
|
10
10
|
|
|
11
11
|
const isOpen = ref(false)
|
|
12
12
|
|
|
13
|
-
const groupId = computed(
|
|
14
|
-
`NavScreenGroup-${props.text.replace(' ', '-').toLowerCase()}`
|
|
13
|
+
const groupId = computed(
|
|
14
|
+
() => `NavScreenGroup-${props.text.replace(' ', '-').toLowerCase()}`
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
function toggle() {
|
|
@@ -32,16 +32,17 @@ function toggle() {
|
|
|
32
32
|
</button>
|
|
33
33
|
|
|
34
34
|
<div :id="groupId" class="items">
|
|
35
|
-
<template v-for="item in items" :key="item
|
|
36
|
-
<div v-if="'link' in item"
|
|
35
|
+
<template v-for="item in items" :key="JSON.stringify(item)">
|
|
36
|
+
<div v-if="'link' in item" class="item">
|
|
37
37
|
<VPNavScreenMenuGroupLink :item="item" />
|
|
38
38
|
</div>
|
|
39
39
|
|
|
40
|
+
<div v-else-if="'component' in item" class="item">
|
|
41
|
+
<component :is="item.component" v-bind="item.props" screen-menu />
|
|
42
|
+
</div>
|
|
43
|
+
|
|
40
44
|
<div v-else class="group">
|
|
41
|
-
<VPNavScreenMenuGroupSection
|
|
42
|
-
:text="item.text"
|
|
43
|
-
:items="item.items"
|
|
44
|
-
/>
|
|
45
|
+
<VPNavScreenMenuGroupSection :items="item.items" />
|
|
45
46
|
</div>
|
|
46
47
|
</template>
|
|
47
48
|
</div>
|
|
@@ -3,7 +3,7 @@ import { useScrollLock } from '@vueuse/core'
|
|
|
3
3
|
import { inBrowser } from 'vitepress'
|
|
4
4
|
import { ref, watch } from 'vue'
|
|
5
5
|
import { useSidebar } from '../composables/sidebar'
|
|
6
|
-
import
|
|
6
|
+
import VPSidebarGroup from './VPSidebarGroup.vue'
|
|
7
7
|
|
|
8
8
|
const { sidebarGroups, hasSidebar } = useSidebar()
|
|
9
9
|
|
|
@@ -25,6 +25,16 @@ watch(
|
|
|
25
25
|
},
|
|
26
26
|
{ immediate: true, flush: 'post' }
|
|
27
27
|
)
|
|
28
|
+
|
|
29
|
+
const key = ref(0)
|
|
30
|
+
|
|
31
|
+
watch(
|
|
32
|
+
sidebarGroups,
|
|
33
|
+
() => {
|
|
34
|
+
key.value += 1
|
|
35
|
+
},
|
|
36
|
+
{ deep: true }
|
|
37
|
+
)
|
|
28
38
|
</script>
|
|
29
39
|
|
|
30
40
|
<template>
|
|
@@ -37,17 +47,18 @@ watch(
|
|
|
37
47
|
>
|
|
38
48
|
<div class="curtain" />
|
|
39
49
|
|
|
40
|
-
<nav
|
|
50
|
+
<nav
|
|
51
|
+
class="nav"
|
|
52
|
+
id="VPSidebarNav"
|
|
53
|
+
aria-labelledby="sidebar-aria-label"
|
|
54
|
+
tabindex="-1"
|
|
55
|
+
>
|
|
41
56
|
<span class="visually-hidden" id="sidebar-aria-label">
|
|
42
57
|
Sidebar Navigation
|
|
43
58
|
</span>
|
|
44
59
|
|
|
45
60
|
<slot name="sidebar-nav-before" />
|
|
46
|
-
|
|
47
|
-
<div v-for="item in sidebarGroups" :key="item.text" class="group">
|
|
48
|
-
<VPSidebarItem :item="item" :depth="0" />
|
|
49
|
-
</div>
|
|
50
|
-
|
|
61
|
+
<VPSidebarGroup :items="sidebarGroups" :key="key" />
|
|
51
62
|
<slot name="sidebar-nav-after" />
|
|
52
63
|
</nav>
|
|
53
64
|
</aside>
|
|
@@ -122,16 +133,4 @@ watch(
|
|
|
122
133
|
.nav {
|
|
123
134
|
outline: 0;
|
|
124
135
|
}
|
|
125
|
-
|
|
126
|
-
.group + .group {
|
|
127
|
-
border-top: 1px solid var(--vp-c-divider);
|
|
128
|
-
padding-top: 10px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@media (min-width: 960px) {
|
|
132
|
-
.group {
|
|
133
|
-
padding-top: 10px;
|
|
134
|
-
width: calc(var(--vp-sidebar-width) - 64px);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
136
|
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
+
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
|
4
|
+
import VPSidebarItem from './VPSidebarItem.vue'
|
|
5
|
+
|
|
6
|
+
defineProps<{
|
|
7
|
+
items: DefaultTheme.SidebarItem[]
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const disableTransition = ref(true)
|
|
11
|
+
|
|
12
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
13
|
+
|
|
14
|
+
onMounted(() => {
|
|
15
|
+
timer = setTimeout(() => {
|
|
16
|
+
timer = null
|
|
17
|
+
disableTransition.value = false
|
|
18
|
+
}, 300)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
onBeforeUnmount(() => {
|
|
22
|
+
if (timer != null) {
|
|
23
|
+
clearTimeout(timer)
|
|
24
|
+
timer = null
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<div
|
|
31
|
+
v-for="item in items"
|
|
32
|
+
:key="item.text"
|
|
33
|
+
class="group"
|
|
34
|
+
:class="{ 'no-transition': disableTransition }"
|
|
35
|
+
>
|
|
36
|
+
<VPSidebarItem :item="item" :depth="0" />
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<style scoped>
|
|
41
|
+
.no-transition :deep(.caret-icon) {
|
|
42
|
+
transition: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.group + .group {
|
|
46
|
+
border-top: 1px solid var(--vp-c-divider);
|
|
47
|
+
padding-top: 10px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@media (min-width: 960px) {
|
|
51
|
+
.group {
|
|
52
|
+
padding-top: 10px;
|
|
53
|
+
width: calc(var(--vp-sidebar-width) - 64px);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue'
|
|
3
2
|
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
4
|
import { useSidebarControl } from '../composables/sidebar'
|
|
5
5
|
import VPLink from './VPLink.vue'
|
|
6
6
|
|
|
@@ -27,8 +27,8 @@ const textTag = computed(() => {
|
|
|
27
27
|
return !hasChildren.value
|
|
28
28
|
? 'p'
|
|
29
29
|
: props.depth + 2 === 7
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
? 'p'
|
|
31
|
+
: `h${props.depth + 2}`
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
const itemRole = computed(() => (isLink.value ? undefined : 'button'))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { inject,
|
|
2
|
+
import { inject, ref, watchPostEffect } from 'vue'
|
|
3
3
|
import { useData } from '../composables/data'
|
|
4
4
|
import VPSwitch from './VPSwitch.vue'
|
|
5
5
|
|
|
@@ -9,8 +9,10 @@ const toggleAppearance = inject('toggle-appearance', () => {
|
|
|
9
9
|
isDark.value = !isDark.value
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
const switchTitle =
|
|
13
|
-
|
|
12
|
+
const switchTitle = ref('')
|
|
13
|
+
|
|
14
|
+
watchPostEffect(() => {
|
|
15
|
+
switchTitle.value = isDark.value
|
|
14
16
|
? theme.value.lightModeSwitchTitle || 'Switch to light theme'
|
|
15
17
|
: theme.value.darkModeSwitchTitle || 'Switch to dark theme'
|
|
16
18
|
})
|
|
@@ -35,6 +35,13 @@
|
|
|
35
35
|
font-size: 20px;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
.vp-doc h4 {
|
|
39
|
+
margin: 24px 0 0;
|
|
40
|
+
letter-spacing: -0.01em;
|
|
41
|
+
line-height: 24px;
|
|
42
|
+
font-size: 18px;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
.vp-doc .header-anchor {
|
|
39
46
|
position: absolute;
|
|
40
47
|
top: 0;
|
|
@@ -98,12 +105,12 @@
|
|
|
98
105
|
border-left: 2px solid var(--vp-c-divider);
|
|
99
106
|
padding-left: 16px;
|
|
100
107
|
transition: border-color 0.5s;
|
|
108
|
+
color: var(--vp-c-text-2);
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
.vp-doc blockquote > p {
|
|
104
112
|
margin: 0;
|
|
105
113
|
font-size: 16px;
|
|
106
|
-
color: var(--vp-c-text-2);
|
|
107
114
|
transition: color 0.5s;
|
|
108
115
|
}
|
|
109
116
|
|
|
@@ -262,7 +269,8 @@
|
|
|
262
269
|
|
|
263
270
|
.vp-doc h1 > code,
|
|
264
271
|
.vp-doc h2 > code,
|
|
265
|
-
.vp-doc h3 > code
|
|
272
|
+
.vp-doc h3 > code,
|
|
273
|
+
.vp-doc h4 > code {
|
|
266
274
|
font-size: 0.9em;
|
|
267
275
|
}
|
|
268
276
|
|