vitepress 1.0.0-beta.2 → 1.0.0-beta.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/dist/client/app/composables/copyCode.js +2 -3
- package/dist/client/app/composables/preFetch.js +3 -3
- package/dist/client/app/index.js +11 -10
- package/dist/client/app/router.js +26 -15
- package/dist/client/app/utils.js +2 -0
- package/dist/client/index.d.ts +22 -4
- package/dist/client/index.js +1 -1
- package/dist/client/theme-default/Layout.vue +10 -9
- package/dist/client/theme-default/components/VPContent.vue +4 -4
- package/dist/client/theme-default/components/VPDoc.vue +15 -2
- package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +9 -3
- package/dist/client/theme-default/components/VPDocOutlineItem.vue +2 -4
- package/dist/client/theme-default/components/VPFooter.vue +1 -1
- package/dist/client/theme-default/components/VPLink.vue +1 -16
- package/dist/client/theme-default/components/VPLocalNav.vue +2 -2
- package/dist/client/theme-default/components/VPLocalSearchBox.vue +3 -3
- package/dist/client/theme-default/components/VPNavBar.vue +7 -7
- package/dist/client/theme-default/components/VPNavBarSearch.vue +3 -1
- package/dist/client/theme-default/components/VPNavBarTitle.vue +1 -1
- package/dist/client/theme-default/components/VPSidebar.vue +2 -2
- package/dist/client/theme-default/components/VPSkipLink.vue +2 -2
- package/dist/client/theme-default/composables/aside.js +2 -2
- package/dist/client/theme-default/styles/components/vp-doc.css +21 -0
- package/dist/client/theme-default/support/utils.js +1 -1
- package/dist/client/theme-default/without-fonts.js +1 -0
- package/dist/node/cli.js +2 -2
- package/dist/node/index.d.ts +5 -3
- package/dist/node/index.js +2 -2
- package/dist/node/{serve-9050e258.js → serve-d0f912b9.js} +1233 -1088
- package/dist/node-cjs/cli.cjs +2 -2
- package/dist/node-cjs/index.cjs +1 -1
- package/dist/node-cjs/{serve-1a76c42b.cjs → serve-3371ae61.cjs} +1242 -1097
- package/package.json +52 -51
- package/template/.vitepress/theme/index.js +1 -1
- package/theme.d.ts +2 -1
- package/types/default-theme.d.ts +48 -2
- package/dist/client/theme-default/components/icons/VPIconExternalLink.vue +0 -13
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { inBrowser } from 'vitepress';
|
|
2
2
|
export function useCopyCode() {
|
|
3
3
|
if (inBrowser) {
|
|
4
|
-
const timeoutIdMap = new
|
|
4
|
+
const timeoutIdMap = new WeakMap();
|
|
5
5
|
window.addEventListener('click', (e) => {
|
|
6
6
|
const el = e.target;
|
|
7
7
|
if (el.matches('div[class*="language-"] > button.copy')) {
|
|
8
8
|
const parent = el.parentElement;
|
|
9
|
-
const sibling = el.nextElementSibling
|
|
10
|
-
?.nextElementSibling;
|
|
9
|
+
const sibling = el.nextElementSibling?.nextElementSibling;
|
|
11
10
|
if (!parent || !sibling) {
|
|
12
11
|
return;
|
|
13
12
|
}
|
|
@@ -52,7 +52,8 @@ export function usePrefetch() {
|
|
|
52
52
|
if (!hasFetched.has(pathname)) {
|
|
53
53
|
hasFetched.add(pathname);
|
|
54
54
|
const pageChunkPath = pathToFile(pathname);
|
|
55
|
-
|
|
55
|
+
if (pageChunkPath)
|
|
56
|
+
doFetch(pageChunkPath);
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
});
|
|
@@ -61,7 +62,6 @@ export function usePrefetch() {
|
|
|
61
62
|
document
|
|
62
63
|
.querySelectorAll('#app a')
|
|
63
64
|
.forEach((link) => {
|
|
64
|
-
const { target } = link;
|
|
65
65
|
const { hostname, pathname } = new URL(link.href instanceof SVGAnimatedString
|
|
66
66
|
? link.href.animVal
|
|
67
67
|
: link.href, link.baseURI);
|
|
@@ -72,7 +72,7 @@ export function usePrefetch() {
|
|
|
72
72
|
if (
|
|
73
73
|
// only prefetch same tab navigation, since a new tab will load
|
|
74
74
|
// the lean js chunk instead.
|
|
75
|
-
target !==
|
|
75
|
+
link.target !== '_blank' &&
|
|
76
76
|
// only prefetch inbound links
|
|
77
77
|
hostname === location.hostname) {
|
|
78
78
|
if (pathname !== location.pathname) {
|
package/dist/client/app/index.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { createApp as createClientApp, createSSRApp, defineComponent, h, onMounted, watchEffect } from 'vue';
|
|
2
1
|
import RawTheme from '@theme/index';
|
|
3
|
-
import {
|
|
4
|
-
import { RouterSymbol, createRouter, scrollTo } from './router';
|
|
5
|
-
import { siteDataRef, useData } from './data';
|
|
6
|
-
import { useUpdateHead } from './composables/head';
|
|
7
|
-
import { usePrefetch } from './composables/preFetch';
|
|
8
|
-
import { dataSymbol, initData } from './data';
|
|
9
|
-
import { Content } from './components/Content';
|
|
2
|
+
import { createApp as createClientApp, createSSRApp, defineComponent, h, onMounted, watchEffect } from 'vue';
|
|
10
3
|
import { ClientOnly } from './components/ClientOnly';
|
|
11
|
-
import {
|
|
4
|
+
import { Content } from './components/Content';
|
|
12
5
|
import { useCodeGroups } from './composables/codeGroups';
|
|
6
|
+
import { useCopyCode } from './composables/copyCode';
|
|
7
|
+
import { useUpdateHead } from './composables/head';
|
|
8
|
+
import { usePrefetch } from './composables/preFetch';
|
|
9
|
+
import { dataSymbol, initData, siteDataRef, useData } from './data';
|
|
10
|
+
import { RouterSymbol, createRouter, scrollTo } from './router';
|
|
11
|
+
import { inBrowser, pathToFile } from './utils';
|
|
13
12
|
function resolveThemeExtends(theme) {
|
|
14
13
|
if (theme.extends) {
|
|
15
14
|
const base = resolveThemeExtends(theme.extends);
|
|
@@ -96,6 +95,8 @@ function newRouter() {
|
|
|
96
95
|
let initialPath;
|
|
97
96
|
return createRouter((path) => {
|
|
98
97
|
let pageFilePath = pathToFile(path);
|
|
98
|
+
if (!pageFilePath)
|
|
99
|
+
return null;
|
|
99
100
|
if (isInitialPageLoad) {
|
|
100
101
|
initialPath = pageFilePath;
|
|
101
102
|
}
|
|
@@ -120,7 +121,7 @@ if (inBrowser) {
|
|
|
120
121
|
app.mount('#app');
|
|
121
122
|
// scroll to hash on new tab during dev
|
|
122
123
|
if (import.meta.env.DEV && location.hash) {
|
|
123
|
-
const target = document.
|
|
124
|
+
const target = document.getElementById(decodeURIComponent(location.hash).slice(1));
|
|
124
125
|
if (target) {
|
|
125
126
|
scrollTo(target, location.hash);
|
|
126
127
|
}
|
|
@@ -5,7 +5,7 @@ import { siteDataRef } from './data';
|
|
|
5
5
|
export const RouterSymbol = Symbol();
|
|
6
6
|
// we are just using URL to parse the pathname and hash - the base doesn't
|
|
7
7
|
// matter and is only passed to support same-host hrefs.
|
|
8
|
-
const fakeHost =
|
|
8
|
+
const fakeHost = 'http://a.com';
|
|
9
9
|
const getDefaultRoute = () => ({
|
|
10
10
|
path: '/',
|
|
11
11
|
component: null,
|
|
@@ -18,7 +18,8 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
18
18
|
go
|
|
19
19
|
};
|
|
20
20
|
async function go(href = inBrowser ? location.href : '/') {
|
|
21
|
-
await router.onBeforeRouteChange?.(href)
|
|
21
|
+
if ((await router.onBeforeRouteChange?.(href)) === false)
|
|
22
|
+
return;
|
|
22
23
|
const url = new URL(href, fakeHost);
|
|
23
24
|
if (!siteDataRef.value.cleanUrls) {
|
|
24
25
|
// ensure correct deep link so page refresh lands on correct files.
|
|
@@ -38,10 +39,15 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
38
39
|
}
|
|
39
40
|
let latestPendingPath = null;
|
|
40
41
|
async function loadPage(href, scrollPosition = 0, isRetry = false) {
|
|
42
|
+
if ((await router.onBeforePageLoad?.(href)) === false)
|
|
43
|
+
return;
|
|
41
44
|
const targetLoc = new URL(href, fakeHost);
|
|
42
45
|
const pendingPath = (latestPendingPath = targetLoc.pathname);
|
|
43
46
|
try {
|
|
44
47
|
let page = await loadPageModule(pendingPath);
|
|
48
|
+
if (!page) {
|
|
49
|
+
throw new Error(`Page not found: ${pendingPath}`);
|
|
50
|
+
}
|
|
45
51
|
if (latestPendingPath === pendingPath) {
|
|
46
52
|
latestPendingPath = null;
|
|
47
53
|
const { default: comp, __pageData } = page;
|
|
@@ -68,7 +74,7 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
68
74
|
if (targetLoc.hash && !scrollPosition) {
|
|
69
75
|
let target = null;
|
|
70
76
|
try {
|
|
71
|
-
target = document.
|
|
77
|
+
target = document.getElementById(decodeURIComponent(targetLoc.hash).slice(1));
|
|
72
78
|
}
|
|
73
79
|
catch (e) {
|
|
74
80
|
console.warn(e);
|
|
@@ -84,7 +90,8 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
catch (err) {
|
|
87
|
-
if (!/fetch/.test(err.message) &&
|
|
93
|
+
if (!/fetch|Page not found/.test(err.message) &&
|
|
94
|
+
!/^\/404(\.html|\/)?$/.test(href)) {
|
|
88
95
|
console.error(err);
|
|
89
96
|
}
|
|
90
97
|
// retry on fetch fail: the page to hash map may have been invalidated
|
|
@@ -128,7 +135,7 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
128
135
|
!e.shiftKey &&
|
|
129
136
|
!e.altKey &&
|
|
130
137
|
!e.metaKey &&
|
|
131
|
-
target
|
|
138
|
+
!target &&
|
|
132
139
|
origin === currentUrl.origin &&
|
|
133
140
|
// don't intercept if non-html extension is present
|
|
134
141
|
!(extMatch && extMatch[0] !== '.html')) {
|
|
@@ -178,7 +185,7 @@ export function scrollTo(el, hash, smooth = false) {
|
|
|
178
185
|
try {
|
|
179
186
|
target = el.classList.contains('header-anchor')
|
|
180
187
|
? el
|
|
181
|
-
: document.
|
|
188
|
+
: document.getElementById(decodeURIComponent(hash).slice(1));
|
|
182
189
|
}
|
|
183
190
|
catch (e) {
|
|
184
191
|
console.warn(e);
|
|
@@ -207,16 +214,20 @@ export function scrollTo(el, hash, smooth = false) {
|
|
|
207
214
|
offset +
|
|
208
215
|
targetPadding;
|
|
209
216
|
// only smooth scroll if distance is smaller than screen height.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
function scrollToTarget() {
|
|
218
|
+
if (!smooth ||
|
|
219
|
+
Math.abs(targetTop - window.scrollY) > window.innerHeight) {
|
|
220
|
+
window.scrollTo(0, targetTop);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
window.scrollTo({
|
|
224
|
+
left: 0,
|
|
225
|
+
top: targetTop,
|
|
226
|
+
behavior: 'smooth'
|
|
227
|
+
});
|
|
228
|
+
}
|
|
219
229
|
}
|
|
230
|
+
requestAnimationFrame(scrollToTarget);
|
|
220
231
|
}
|
|
221
232
|
}
|
|
222
233
|
function tryOffsetSelector(selector) {
|
package/dist/client/app/utils.js
CHANGED
package/dist/client/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
|
-
import { Component, Ref, App, AsyncComponentLoader } from 'vue';
|
|
2
|
+
import { Component, InjectionKey, Ref, App, AsyncComponentLoader } from 'vue';
|
|
3
3
|
import { PageData, Awaitable, SiteData } from '../../types/shared.js';
|
|
4
4
|
export { HeadConfig, Header, PageData, SiteData } from '../../types/shared.js';
|
|
5
5
|
|
|
@@ -11,14 +11,32 @@ interface Route {
|
|
|
11
11
|
component: Component | null;
|
|
12
12
|
}
|
|
13
13
|
interface Router {
|
|
14
|
+
/**
|
|
15
|
+
* Current route.
|
|
16
|
+
*/
|
|
14
17
|
route: Route;
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Navigate to a new URL.
|
|
20
|
+
*/
|
|
21
|
+
go: (to?: string) => Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Called before the route changes. Return `false` to cancel the navigation.
|
|
24
|
+
*/
|
|
25
|
+
onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Called before the page component is loaded (after the history state is
|
|
28
|
+
* updated). Return `false` to cancel the navigation.
|
|
29
|
+
*/
|
|
30
|
+
onBeforePageLoad?: (to: string) => Awaitable<void | boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Called after the route changes.
|
|
33
|
+
*/
|
|
17
34
|
onAfterRouteChanged?: (to: string) => Awaitable<void>;
|
|
18
35
|
}
|
|
19
36
|
declare function useRouter(): Router;
|
|
20
37
|
declare function useRoute(): Route;
|
|
21
38
|
|
|
39
|
+
declare const dataSymbol: InjectionKey<VitePressData>;
|
|
22
40
|
interface VitePressData<T = any> {
|
|
23
41
|
/**
|
|
24
42
|
* Site-level metadata
|
|
@@ -96,4 +114,4 @@ declare const Content: vue.DefineComponent<{
|
|
|
96
114
|
as: string | Record<string, any>;
|
|
97
115
|
}, {}>;
|
|
98
116
|
|
|
99
|
-
export { Content, EnhanceAppContext, Route, Router, Theme, VitePressData, defineClientComponent, inBrowser, onContentUpdated, useData, useRoute, useRouter, withBase };
|
|
117
|
+
export { Content, EnhanceAppContext, Route, Router, Theme, VitePressData, dataSymbol, defineClientComponent, inBrowser, onContentUpdated, useData, useRoute, useRouter, withBase };
|
package/dist/client/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// exports in this file are exposed to themes and md files via 'vitepress'
|
|
2
2
|
// so the user can do `import { useRoute, useSiteData } from 'vitepress'`
|
|
3
3
|
// composables
|
|
4
|
-
export { useData } from './app/data';
|
|
4
|
+
export { useData, dataSymbol } from './app/data';
|
|
5
5
|
export { useRoute, useRouter } from './app/router';
|
|
6
6
|
// utilities
|
|
7
7
|
export { inBrowser, onContentUpdated, defineClientComponent, withBase } from './app/utils';
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, provide, useSlots, watch } from 'vue'
|
|
3
2
|
import { useRoute } from 'vitepress'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import VPSkipLink from './components/VPSkipLink.vue'
|
|
3
|
+
import { useSidebar } from 'vitepress/theme'
|
|
4
|
+
import { computed, provide, useSlots, watch } from 'vue'
|
|
7
5
|
import VPBackdrop from './components/VPBackdrop.vue'
|
|
8
|
-
import VPNav from './components/VPNav.vue'
|
|
9
|
-
import VPLocalNav from './components/VPLocalNav.vue'
|
|
10
|
-
import VPSidebar from './components/VPSidebar.vue'
|
|
11
6
|
import VPContent from './components/VPContent.vue'
|
|
12
7
|
import VPFooter from './components/VPFooter.vue'
|
|
8
|
+
import VPLocalNav from './components/VPLocalNav.vue'
|
|
9
|
+
import VPNav from './components/VPNav.vue'
|
|
10
|
+
import VPSidebar from './components/VPSidebar.vue'
|
|
11
|
+
import VPSkipLink from './components/VPSkipLink.vue'
|
|
12
|
+
import { useData } from './composables/data'
|
|
13
|
+
import { useCloseSidebarOnEscape } from './composables/sidebar'
|
|
13
14
|
|
|
14
15
|
const {
|
|
15
16
|
isOpen: isSidebarOpen,
|
|
@@ -38,7 +39,7 @@ provide('hero-image-slot-exists', heroImageSlotExists)
|
|
|
38
39
|
<slot name="layout-top" />
|
|
39
40
|
<VPSkipLink />
|
|
40
41
|
<VPBackdrop class="backdrop" :show="isSidebarOpen" @click="closeSidebar" />
|
|
41
|
-
<VPNav>
|
|
42
|
+
<VPNav v-if="frontmatter.navbar !== false">
|
|
42
43
|
<template #nav-bar-title-before><slot name="nav-bar-title-before" /></template>
|
|
43
44
|
<template #nav-bar-title-after><slot name="nav-bar-title-after" /></template>
|
|
44
45
|
<template #nav-bar-content-before><slot name="nav-bar-content-before" /></template>
|
|
@@ -56,7 +57,7 @@ provide('hero-image-slot-exists', heroImageSlotExists)
|
|
|
56
57
|
<VPContent>
|
|
57
58
|
<template #page-top><slot name="page-top" /></template>
|
|
58
59
|
<template #page-bottom><slot name="page-bottom" /></template>
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
<template #not-found><slot name="not-found" /></template>
|
|
61
62
|
<template #home-hero-before><slot name="home-hero-before" /></template>
|
|
62
63
|
<template #home-hero-info><slot name="home-hero-info" /></template>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useSidebar } from 'vitepress/theme'
|
|
3
|
+
import NotFound from '../NotFound.vue'
|
|
2
4
|
import { useData } from '../composables/data'
|
|
3
|
-
import { useSidebar } from '../composables/sidebar'
|
|
4
|
-
import VPPage from './VPPage.vue'
|
|
5
|
-
import VPHome from './VPHome.vue'
|
|
6
5
|
import VPDoc from './VPDoc.vue'
|
|
7
|
-
import
|
|
6
|
+
import VPHome from './VPHome.vue'
|
|
7
|
+
import VPPage from './VPPage.vue'
|
|
8
8
|
|
|
9
9
|
const { page, frontmatter } = useData()
|
|
10
10
|
const { hasSidebar } = useSidebar()
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useRoute } from 'vitepress'
|
|
3
|
+
import { useSidebar } from 'vitepress/theme'
|
|
3
4
|
import { computed } from 'vue'
|
|
4
|
-
import {
|
|
5
|
+
import { useData } from '../composables/data'
|
|
5
6
|
import VPDocAside from './VPDocAside.vue'
|
|
6
7
|
import VPDocFooter from './VPDocFooter.vue'
|
|
7
8
|
import VPDocOutlineDropdown from './VPDocOutlineDropdown.vue'
|
|
8
9
|
|
|
10
|
+
const { theme } = useData()
|
|
11
|
+
|
|
9
12
|
const route = useRoute()
|
|
10
13
|
const { hasSidebar, hasAside, leftAside } = useSidebar()
|
|
11
14
|
|
|
@@ -42,7 +45,13 @@ const pageName = computed(() =>
|
|
|
42
45
|
<slot name="doc-before" />
|
|
43
46
|
<VPDocOutlineDropdown />
|
|
44
47
|
<main class="main">
|
|
45
|
-
<Content
|
|
48
|
+
<Content
|
|
49
|
+
class="vp-doc"
|
|
50
|
+
:class="[
|
|
51
|
+
pageName,
|
|
52
|
+
theme.externalLinkIcon && 'external-link-icon-enabled'
|
|
53
|
+
]"
|
|
54
|
+
/>
|
|
46
55
|
</main>
|
|
47
56
|
<VPDocFooter>
|
|
48
57
|
<template #doc-footer-before><slot name="doc-footer-before" /></template>
|
|
@@ -193,4 +202,8 @@ const pageName = computed(() =>
|
|
|
193
202
|
.VPDoc.has-aside .content-container {
|
|
194
203
|
max-width: 688px;
|
|
195
204
|
}
|
|
205
|
+
|
|
206
|
+
.external-link-icon-enabled :is(.vp-doc a[href*='://'], .vp-doc a[target='_blank'])::after {
|
|
207
|
+
content: '';
|
|
208
|
+
}
|
|
196
209
|
</style>
|
|
@@ -2,7 +2,7 @@
|
|
|
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 } = useData()
|
|
6
6
|
|
|
7
7
|
const date = computed(() => new Date(page.value.lastUpdated!))
|
|
8
8
|
const isoDatetime = computed(() => date.value.toISOString())
|
|
@@ -12,14 +12,20 @@ const datetime = ref('')
|
|
|
12
12
|
// potential differences in timezones of the server and clients
|
|
13
13
|
onMounted(() => {
|
|
14
14
|
watchEffect(() => {
|
|
15
|
-
datetime.value =
|
|
15
|
+
datetime.value = new Intl.DateTimeFormat(
|
|
16
|
+
undefined,
|
|
17
|
+
theme.value.lastUpdated?.formatOptions ?? {
|
|
18
|
+
dateStyle: 'short',
|
|
19
|
+
timeStyle: 'short'
|
|
20
|
+
}
|
|
21
|
+
).format(date.value)
|
|
16
22
|
})
|
|
17
23
|
})
|
|
18
24
|
</script>
|
|
19
25
|
|
|
20
26
|
<template>
|
|
21
27
|
<p class="VPLastUpdated">
|
|
22
|
-
{{ theme.lastUpdatedText || 'Last updated' }}:
|
|
28
|
+
{{ theme.lastUpdated?.text || theme.lastUpdatedText || 'Last updated' }}:
|
|
23
29
|
<time :datetime="isoDatetime">{{ datetime }}</time>
|
|
24
30
|
</p>
|
|
25
31
|
</template>
|
|
@@ -7,10 +7,8 @@ defineProps<{
|
|
|
7
7
|
}>()
|
|
8
8
|
|
|
9
9
|
function onClick({ target: el }: Event) {
|
|
10
|
-
const id =
|
|
11
|
-
const heading = document.
|
|
12
|
-
decodeURIComponent(id)
|
|
13
|
-
)
|
|
10
|
+
const id = (el as HTMLAnchorElement).href!.split('#')[1]
|
|
11
|
+
const heading = document.getElementById(decodeURIComponent(id))
|
|
14
12
|
heading?.focus()
|
|
15
13
|
}
|
|
16
14
|
</script>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { normalizeLink } from '../support/utils'
|
|
4
|
-
import VPIconExternalLink from './icons/VPIconExternalLink.vue'
|
|
5
4
|
import { EXTERNAL_URL_RE } from '../../shared'
|
|
6
5
|
|
|
7
6
|
const props = defineProps<{
|
|
@@ -20,25 +19,11 @@ const isExternal = computed(() => props.href && EXTERNAL_URL_RE.test(props.href)
|
|
|
20
19
|
<component
|
|
21
20
|
:is="tag"
|
|
22
21
|
class="VPLink"
|
|
23
|
-
:class="{ link: href }"
|
|
22
|
+
:class="{ link: href, 'vp-external-link-icon': isExternal && !noIcon }"
|
|
24
23
|
:href="href ? normalizeLink(href) : undefined"
|
|
25
24
|
:target="target || (isExternal ? '_blank' : undefined)"
|
|
26
25
|
:rel="rel || (isExternal ? 'noreferrer' : undefined)"
|
|
27
26
|
>
|
|
28
27
|
<slot />
|
|
29
|
-
<VPIconExternalLink v-if="isExternal && !noIcon" class="icon" />
|
|
30
28
|
</component>
|
|
31
29
|
</template>
|
|
32
|
-
|
|
33
|
-
<style scoped>
|
|
34
|
-
.icon {
|
|
35
|
-
display: inline-block;
|
|
36
|
-
margin-top: -1px;
|
|
37
|
-
margin-left: 4px;
|
|
38
|
-
width: 11px;
|
|
39
|
-
height: 11px;
|
|
40
|
-
fill: var(--vp-c-text-3);
|
|
41
|
-
transition: fill 0.25s;
|
|
42
|
-
flex-shrink: 0;
|
|
43
|
-
}
|
|
44
|
-
</style>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { useWindowScroll } from '@vueuse/core'
|
|
3
|
-
import { computed, shallowRef } from 'vue'
|
|
4
3
|
import { onContentUpdated } from 'vitepress'
|
|
4
|
+
import { useSidebar } from 'vitepress/theme'
|
|
5
|
+
import { computed, shallowRef } from 'vue'
|
|
5
6
|
import { useData } from '../composables/data'
|
|
6
7
|
import { getHeaders, type MenuItem } from '../composables/outline'
|
|
7
|
-
import { useSidebar } from '../composables/sidebar'
|
|
8
8
|
import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue'
|
|
9
9
|
import VPIconAlignLeft from './icons/VPIconAlignLeft.vue'
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
|
|
13
13
|
import Mark from 'mark.js/src/vanilla.js'
|
|
14
14
|
import MiniSearch, { type SearchResult } from 'minisearch'
|
|
15
|
-
import { useRouter } from 'vitepress'
|
|
15
|
+
import { useRouter, dataSymbol } from 'vitepress'
|
|
16
16
|
import {
|
|
17
17
|
computed,
|
|
18
18
|
createApp,
|
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
type Ref
|
|
28
28
|
} from 'vue'
|
|
29
29
|
import type { ModalTranslations } from '../../../../types/local-search'
|
|
30
|
-
import { dataSymbol } from '../../app/data'
|
|
31
30
|
import { pathToFile } from '../../app/utils'
|
|
32
31
|
import { useData } from '../composables/data'
|
|
33
32
|
import { createTranslate } from '../support/translation'
|
|
@@ -231,6 +230,7 @@ debouncedWatch(
|
|
|
231
230
|
async function fetchExcerpt(id: string) {
|
|
232
231
|
const file = pathToFile(id.slice(0, id.indexOf('#')))
|
|
233
232
|
try {
|
|
233
|
+
if (!file) throw new Error(`Cannot find file for id: ${id}`)
|
|
234
234
|
return { id, mod: await import(/*@vite-ignore*/ file) }
|
|
235
235
|
} catch (e) {
|
|
236
236
|
console.error(e)
|
|
@@ -421,7 +421,7 @@ function formMarkRegex(terms: Set<string>) {
|
|
|
421
421
|
<button
|
|
422
422
|
class="back-button"
|
|
423
423
|
:title="$t('modal.backButtonTitle')"
|
|
424
|
-
@click="
|
|
424
|
+
@click="$emit('close')"
|
|
425
425
|
>
|
|
426
426
|
<svg
|
|
427
427
|
width="18"
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed } from 'vue'
|
|
3
2
|
import { useWindowScroll } from '@vueuse/core'
|
|
4
|
-
import { useSidebar } from '
|
|
5
|
-
import
|
|
6
|
-
import VPNavBarSearch from './VPNavBarSearch.vue'
|
|
7
|
-
import VPNavBarMenu from './VPNavBarMenu.vue'
|
|
8
|
-
import VPNavBarTranslations from './VPNavBarTranslations.vue'
|
|
3
|
+
import { useSidebar } from 'vitepress/theme'
|
|
4
|
+
import { computed } from 'vue'
|
|
9
5
|
import VPNavBarAppearance from './VPNavBarAppearance.vue'
|
|
10
|
-
import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
|
|
11
6
|
import VPNavBarExtra from './VPNavBarExtra.vue'
|
|
12
7
|
import VPNavBarHamburger from './VPNavBarHamburger.vue'
|
|
8
|
+
import VPNavBarMenu from './VPNavBarMenu.vue'
|
|
9
|
+
import VPNavBarSearch from './VPNavBarSearch.vue'
|
|
10
|
+
import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
|
|
11
|
+
import VPNavBarTitle from './VPNavBarTitle.vue'
|
|
12
|
+
import VPNavBarTranslations from './VPNavBarTranslations.vue'
|
|
13
13
|
|
|
14
14
|
defineProps<{
|
|
15
15
|
isScreenOpen: boolean
|
|
@@ -26,6 +26,7 @@ const { theme, localeIndex } = useData()
|
|
|
26
26
|
// payload), we delay initializing it until the user has actually clicked or
|
|
27
27
|
// hit the hotkey to invoke it.
|
|
28
28
|
const loaded = ref(false)
|
|
29
|
+
const actuallyLoaded = ref(false)
|
|
29
30
|
|
|
30
31
|
const buttonText = computed(() => {
|
|
31
32
|
const options = theme.value.search?.options ?? theme.value.algolia
|
|
@@ -169,9 +170,10 @@ const provider = __ALGOLIA__ ? 'algolia' : __VP_LOCAL_SEARCH__ ? 'local' : ''
|
|
|
169
170
|
<VPAlgoliaSearchBox
|
|
170
171
|
v-if="loaded"
|
|
171
172
|
:algolia="theme.search?.options ?? theme.algolia"
|
|
173
|
+
@vue:beforeMount="actuallyLoaded = true"
|
|
172
174
|
/>
|
|
173
175
|
|
|
174
|
-
<div v-
|
|
176
|
+
<div v-if="!actuallyLoaded" id="docsearch">
|
|
175
177
|
<VPNavBarSearchButton :placeholder="buttonText" @click="load" />
|
|
176
178
|
</div>
|
|
177
179
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useSidebar } from 'vitepress/theme'
|
|
2
3
|
import { useData } from '../composables/data'
|
|
3
|
-
import { useSidebar } from '../composables/sidebar'
|
|
4
4
|
import { useLangs } from '../composables/langs'
|
|
5
5
|
import { normalizeLink } from '../support/utils'
|
|
6
6
|
import VPImage from './VPImage.vue'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { clearAllBodyScrollLocks, disableBodyScroll } from 'body-scroll-lock'
|
|
3
|
+
import { useSidebar } from 'vitepress/theme'
|
|
2
4
|
import { ref, watchPostEffect } from 'vue'
|
|
3
|
-
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock'
|
|
4
|
-
import { useSidebar } from '../composables/sidebar'
|
|
5
5
|
import VPSidebarItem from './VPSidebarItem.vue'
|
|
6
6
|
|
|
7
7
|
const { sidebarGroups, hasSidebar } = useSidebar()
|
|
@@ -8,8 +8,8 @@ const backToTop = ref()
|
|
|
8
8
|
watch(() => route.path, () => backToTop.value.focus())
|
|
9
9
|
|
|
10
10
|
function focusOnTargetAnchor({ target }: Event) {
|
|
11
|
-
const el = document.
|
|
12
|
-
decodeURIComponent((target as HTMLAnchorElement).hash)
|
|
11
|
+
const el = document.getElementById(
|
|
12
|
+
decodeURIComponent((target as HTMLAnchorElement).hash).slice(1)
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
if (el) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { computed } from 'vue';
|
|
2
1
|
import { useMediaQuery } from '@vueuse/core';
|
|
3
|
-
import { useSidebar } from '
|
|
2
|
+
import { useSidebar } from 'vitepress/theme';
|
|
3
|
+
import { computed } from 'vue';
|
|
4
4
|
export function useAside() {
|
|
5
5
|
const { hasSidebar } = useSidebar();
|
|
6
6
|
const is960 = useMediaQuery('(min-width: 960px)');
|
|
@@ -522,3 +522,24 @@
|
|
|
522
522
|
margin: 0 !important;
|
|
523
523
|
max-width: calc((100% - 24px) / 2) !important;
|
|
524
524
|
}
|
|
525
|
+
|
|
526
|
+
:is(
|
|
527
|
+
.vp-external-link-icon,
|
|
528
|
+
.vp-doc a[href*='://'],
|
|
529
|
+
.vp-doc a[target='_blank']
|
|
530
|
+
)::after {
|
|
531
|
+
display: inline-block;
|
|
532
|
+
margin-top: -1px;
|
|
533
|
+
margin-left: 4px;
|
|
534
|
+
width: 11px;
|
|
535
|
+
height: 11px;
|
|
536
|
+
background: currentColor;
|
|
537
|
+
flex-shrink: 0;
|
|
538
|
+
--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");
|
|
539
|
+
-webkit-mask-image: var(--icon);
|
|
540
|
+
mask-image: var(--icon);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.vp-external-link-icon::after {
|
|
544
|
+
content: '';
|
|
545
|
+
}
|
|
@@ -28,7 +28,7 @@ export function normalizeLink(url) {
|
|
|
28
28
|
return url.replace(PATHNAME_PROTOCOL_RE, '');
|
|
29
29
|
}
|
|
30
30
|
const { site } = useData();
|
|
31
|
-
const { pathname, search, hash } = new URL(url, 'http://
|
|
31
|
+
const { pathname, search, hash } = new URL(url, 'http://a.com');
|
|
32
32
|
const normalizedPath = pathname.endsWith('/') || pathname.endsWith('.html')
|
|
33
33
|
? url
|
|
34
34
|
: url.replace(/(?:(^\.+)\/)?.*$/, `$1${pathname.replace(/(\.md)?$/, site.value.cleanUrls ? '' : '.html')}${search}${hash}`);
|
|
@@ -19,6 +19,7 @@ export { default as VPTeamPage } from './components/VPTeamPage.vue';
|
|
|
19
19
|
export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue';
|
|
20
20
|
export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue';
|
|
21
21
|
export { default as VPTeamMembers } from './components/VPTeamMembers.vue';
|
|
22
|
+
export { useSidebar } from './composables/sidebar';
|
|
22
23
|
const theme = {
|
|
23
24
|
Layout,
|
|
24
25
|
enhanceApp: ({ app }) => {
|
package/dist/node/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as getDefaultExportFromCjs, p as c, q as clearCache, k as build, s as serve, l as init, j as createServer } from './serve-
|
|
1
|
+
import { o as getDefaultExportFromCjs, p as c, q as clearCache, k as build, s as serve, l as init, j as createServer } from './serve-d0f912b9.js';
|
|
2
2
|
import { createLogger } from 'vite';
|
|
3
3
|
import 'url';
|
|
4
4
|
import 'path';
|
|
@@ -294,7 +294,7 @@ var minimist = function (args, opts) {
|
|
|
294
294
|
|
|
295
295
|
var minimist$1 = /*@__PURE__*/getDefaultExportFromCjs(minimist);
|
|
296
296
|
|
|
297
|
-
var version = "1.0.0-beta.
|
|
297
|
+
var version = "1.0.0-beta.4";
|
|
298
298
|
|
|
299
299
|
function bindShortcuts(server, createDevServer) {
|
|
300
300
|
if (!server.httpServer || !process.stdin.isTTY || process.env.CI) {
|