vitepress 1.0.0-alpha.2 → 1.0.0-alpha.5
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/client.d.ts +2 -0
- package/dist/client/app/composables/head.js +7 -41
- package/dist/client/app/data.js +5 -7
- package/dist/client/app/router.js +5 -4
- package/dist/client/shared.js +14 -2
- package/dist/client/theme-default/Layout.vue +16 -2
- package/dist/client/theme-default/components/VPAlgoliaSearchBox.vue +4 -46
- package/dist/client/theme-default/components/VPButton.vue +5 -4
- package/dist/client/theme-default/components/VPContent.vue +4 -1
- package/dist/client/theme-default/components/VPDoc.vue +14 -27
- package/dist/client/theme-default/components/VPDocAsideOutline.vue +3 -1
- package/dist/client/theme-default/components/VPDocFooter.vue +12 -6
- package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +4 -4
- package/dist/client/theme-default/components/VPFlyout.vue +9 -1
- package/dist/client/theme-default/components/VPFooter.vue +2 -2
- package/dist/client/theme-default/components/VPHero.vue +10 -11
- package/dist/client/theme-default/components/VPImage.vue +38 -0
- package/dist/client/theme-default/components/VPLink.vue +3 -2
- package/dist/client/theme-default/components/VPMenu.vue +8 -0
- package/dist/client/theme-default/components/VPNav.vue +11 -2
- package/dist/client/theme-default/components/VPNavBar.vue +12 -2
- package/dist/client/theme-default/components/VPNavBarHamburger.vue +10 -10
- package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +17 -2
- package/dist/client/theme-default/components/VPNavBarMenuLink.vue +1 -1
- package/dist/client/theme-default/components/VPNavBarSearch.vue +23 -6
- package/dist/client/theme-default/components/VPNavBarTitle.vue +5 -2
- package/dist/client/theme-default/components/VPNavScreen.vue +2 -0
- package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +1 -1
- package/dist/client/theme-default/components/VPSidebar.vue +1 -2
- package/dist/client/theme-default/components/VPSidebarGroup.vue +15 -3
- package/dist/client/theme-default/components/VPSidebarLink.vue +26 -11
- package/dist/client/theme-default/components/VPSocialLink.vue +13 -27
- package/dist/client/theme-default/components/VPSocialLinks.vue +1 -1
- package/dist/client/theme-default/components/VPTeamMembers.vue +55 -0
- package/dist/client/theme-default/components/VPTeamMembersItem.vue +215 -0
- package/dist/client/theme-default/components/VPTeamPage.vue +53 -0
- package/dist/client/theme-default/components/VPTeamPageSection.vue +77 -0
- package/dist/client/theme-default/components/VPTeamPageTitle.vue +63 -0
- package/dist/client/theme-default/composables/copy-code.js +46 -8
- package/dist/client/theme-default/composables/nav.js +3 -1
- package/dist/client/theme-default/composables/outline.js +1 -2
- package/dist/client/theme-default/composables/prev-next.js +7 -3
- package/dist/client/theme-default/composables/sidebar.js +12 -3
- package/dist/client/theme-default/fonts/inter-cyrillic-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-cyrillic.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-greek-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-greek.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-cyrillic-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-cyrillic.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-greek-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-greek.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-latin.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-vietnamese.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-latin-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-latin.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-cyrillic-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-cyrillic.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-greek-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-greek.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-latin-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-latin.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-vietnamese.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-vietnamese.woff2 +0 -0
- package/dist/client/theme-default/index.js +4 -0
- package/dist/client/theme-default/styles/base.css +4 -4
- package/dist/client/theme-default/styles/components/vp-doc.css +47 -61
- package/dist/client/theme-default/styles/components/vp-sponsor.css +40 -15
- package/dist/client/theme-default/styles/fonts.css +185 -35
- package/dist/client/theme-default/styles/vars.css +6 -6
- package/dist/client/theme-default/support/sidebar.js +11 -3
- package/dist/client/theme-default/support/socialIcons.js +11 -0
- package/dist/client/theme-default/support/utils.js +2 -2
- package/dist/node/cli.js +10 -4
- package/dist/node/index.d.ts +95 -11
- package/dist/node/index.js +1 -1
- package/dist/node/{serve-42a92e2f.js → serve-111eb887.js} +179 -115
- package/dist/node-cjs/cli.cjs +10 -4
- package/dist/node-cjs/index.cjs +1 -1
- package/dist/node-cjs/{serve-507b373b.cjs → serve-ce0aeb68.cjs} +182 -118
- package/package.json +22 -4
- package/theme.d.ts +9 -5
- package/types/default-theme.d.ts +53 -5
- package/dist/client/theme-default/components/icons/VPIconDiscord.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconFacebook.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconGitHub.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconInstagram.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconLinkedIn.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconSlack.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconTwitter.vue +0 -5
- package/dist/client/theme-default/components/icons/VPIconYouTube.vue +0 -5
- package/dist/client/theme-default/config.js +0 -1
package/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { watchEffect } from 'vue';
|
|
2
|
-
import { createTitle } from '../../shared';
|
|
2
|
+
import { createTitle, mergeHead } from '../../shared';
|
|
3
3
|
export function useUpdateHead(route, siteDataByRouteRef) {
|
|
4
4
|
let managedHeadTags = [];
|
|
5
5
|
let isFirstUpdate = true;
|
|
@@ -10,59 +10,25 @@ export function useUpdateHead(route, siteDataByRouteRef) {
|
|
|
10
10
|
isFirstUpdate = false;
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let el = managedHeadTags[i];
|
|
17
|
-
const [tag, attrs, innerHTML = ''] = newTags[i];
|
|
18
|
-
if (el.tagName.toLocaleLowerCase() === tag) {
|
|
19
|
-
for (const key in attrs) {
|
|
20
|
-
if (el.getAttribute(key) !== attrs[key]) {
|
|
21
|
-
el.setAttribute(key, attrs[key]);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
for (let i = 0; i < el.attributes.length; i++) {
|
|
25
|
-
const name = el.attributes[i].name;
|
|
26
|
-
if (!(name in attrs)) {
|
|
27
|
-
el.removeAttribute(name);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (el.innerHTML !== innerHTML) {
|
|
31
|
-
el.innerHTML = innerHTML;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
document.head.removeChild(el);
|
|
36
|
-
el = createHeadElement(newTags[i]);
|
|
37
|
-
document.head.append(el);
|
|
38
|
-
}
|
|
39
|
-
newEls.push(el);
|
|
40
|
-
}
|
|
41
|
-
managedHeadTags
|
|
42
|
-
.slice(commonLength)
|
|
43
|
-
.forEach((el) => document.head.removeChild(el));
|
|
44
|
-
newTags.slice(commonLength).forEach((headConfig) => {
|
|
13
|
+
managedHeadTags.forEach((el) => document.head.removeChild(el));
|
|
14
|
+
managedHeadTags = [];
|
|
15
|
+
newTags.forEach((headConfig) => {
|
|
45
16
|
const el = createHeadElement(headConfig);
|
|
46
17
|
document.head.appendChild(el);
|
|
47
|
-
|
|
18
|
+
managedHeadTags.push(el);
|
|
48
19
|
});
|
|
49
|
-
managedHeadTags = newEls;
|
|
50
20
|
};
|
|
51
21
|
watchEffect(() => {
|
|
52
22
|
const pageData = route.data;
|
|
53
23
|
const siteData = siteDataByRouteRef.value;
|
|
54
24
|
const pageDescription = pageData && pageData.description;
|
|
55
|
-
const frontmatterHead = pageData && pageData.frontmatter.head;
|
|
25
|
+
const frontmatterHead = (pageData && pageData.frontmatter.head) || [];
|
|
56
26
|
// update title and description
|
|
57
27
|
document.title = createTitle(siteData, pageData);
|
|
58
28
|
document
|
|
59
29
|
.querySelector(`meta[name=description]`)
|
|
60
30
|
.setAttribute('content', pageDescription || siteData.description);
|
|
61
|
-
updateHeadTags(
|
|
62
|
-
// site head can only change during dev
|
|
63
|
-
...(import.meta.env.DEV ? siteData.head : []),
|
|
64
|
-
...(frontmatterHead ? filterOutHeadDescription(frontmatterHead) : [])
|
|
65
|
-
]);
|
|
31
|
+
updateHeadTags(mergeHead(siteData.head, filterOutHeadDescription(frontmatterHead)));
|
|
66
32
|
});
|
|
67
33
|
}
|
|
68
34
|
function createHeadElement([tag, attrs, innerHTML]) {
|
package/dist/client/app/data.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { shallowRef, readonly, computed, inject } from 'vue';
|
|
2
|
-
import
|
|
2
|
+
import siteData from '@siteData';
|
|
3
3
|
import { resolveSiteDataByRoute, createTitle } from '../shared';
|
|
4
4
|
import { withBase } from './utils';
|
|
5
5
|
export const dataSymbol = Symbol();
|
|
6
|
-
export const siteDataRef = shallowRef(
|
|
7
|
-
function parse(data) {
|
|
8
|
-
const parsed = JSON.parse(data);
|
|
9
|
-
return (import.meta.env.DEV ? readonly(parsed) : parsed);
|
|
10
|
-
}
|
|
6
|
+
export const siteDataRef = shallowRef(import.meta.env.PROD ? siteData : readonly(siteData));
|
|
11
7
|
// hmr
|
|
12
8
|
if (import.meta.hot) {
|
|
13
9
|
import.meta.hot.accept('/@siteData', (m) => {
|
|
14
|
-
|
|
10
|
+
if (m) {
|
|
11
|
+
siteDataRef.value = m.default;
|
|
12
|
+
}
|
|
15
13
|
});
|
|
16
14
|
}
|
|
17
15
|
// per-app data
|
|
@@ -97,7 +97,7 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
97
97
|
window.addEventListener('click', (e) => {
|
|
98
98
|
const link = e.target.closest('a');
|
|
99
99
|
if (link) {
|
|
100
|
-
const { href,
|
|
100
|
+
const { href, origin, pathname, hash, search, target } = link;
|
|
101
101
|
const currentUrl = window.location;
|
|
102
102
|
const extMatch = pathname.match(/\.\w+$/);
|
|
103
103
|
// only intercept inbound links
|
|
@@ -106,11 +106,12 @@ export function createRouter(loadPageModule, fallbackComponent) {
|
|
|
106
106
|
!e.altKey &&
|
|
107
107
|
!e.metaKey &&
|
|
108
108
|
target !== `_blank` &&
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
origin === currentUrl.origin &&
|
|
110
|
+
// don't intercept if non-html extension is present
|
|
111
111
|
!(extMatch && extMatch[0] !== '.html')) {
|
|
112
112
|
e.preventDefault();
|
|
113
|
-
if (pathname === currentUrl.pathname
|
|
113
|
+
if (pathname === currentUrl.pathname &&
|
|
114
|
+
search === currentUrl.search) {
|
|
114
115
|
// scroll between hash anchors in the same page
|
|
115
116
|
if (hash && hash !== currentUrl.hash) {
|
|
116
117
|
history.pushState(null, '', hash);
|
package/dist/client/shared.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const EXTERNAL_URL_RE = /^
|
|
1
|
+
export const EXTERNAL_URL_RE = /^[a-z]+:/i;
|
|
2
2
|
export const APPEARANCE_KEY = 'vitepress-theme-appearance';
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
export const inBrowser = typeof window !== 'undefined';
|
|
@@ -7,7 +7,7 @@ export const notFoundPageData = {
|
|
|
7
7
|
title: '404',
|
|
8
8
|
description: 'Not Found',
|
|
9
9
|
headers: [],
|
|
10
|
-
frontmatter: {},
|
|
10
|
+
frontmatter: { sidebar: false, layout: 'page' },
|
|
11
11
|
lastUpdated: 0
|
|
12
12
|
};
|
|
13
13
|
function findMatchRoot(route, roots) {
|
|
@@ -93,3 +93,15 @@ function cleanRoute(siteData, route) {
|
|
|
93
93
|
const baseWithoutSuffix = base.endsWith('/') ? base.slice(0, -1) : base;
|
|
94
94
|
return route.slice(baseWithoutSuffix.length);
|
|
95
95
|
}
|
|
96
|
+
function hasTag(head, tag) {
|
|
97
|
+
const [tagType, tagAttrs] = tag;
|
|
98
|
+
if (tagType !== 'meta')
|
|
99
|
+
return false;
|
|
100
|
+
const keyAttr = Object.entries(tagAttrs)[0]; // First key
|
|
101
|
+
if (keyAttr == null)
|
|
102
|
+
return false;
|
|
103
|
+
return head.some(([type, attrs]) => type === tagType && attrs[keyAttr[0]] === keyAttr[1]);
|
|
104
|
+
}
|
|
105
|
+
export function mergeHead(prev, curr) {
|
|
106
|
+
return [...prev.filter((tagAttrs) => !hasTag(curr, tagAttrs)), ...curr];
|
|
107
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { provide } from 'vue'
|
|
2
|
+
import { provide, watch } from 'vue'
|
|
3
|
+
import { useRoute } from 'vitepress'
|
|
3
4
|
import { useSidebar, useCloseSidebarOnEscape } from './composables/sidebar'
|
|
4
5
|
import VPSkipLink from './components/VPSkipLink.vue'
|
|
5
6
|
import VPBackdrop from './components/VPBackdrop.vue'
|
|
@@ -15,6 +16,9 @@ const {
|
|
|
15
16
|
close: closeSidebar
|
|
16
17
|
} = useSidebar()
|
|
17
18
|
|
|
19
|
+
const route = useRoute()
|
|
20
|
+
watch(() => route.path, closeSidebar)
|
|
21
|
+
|
|
18
22
|
useCloseSidebarOnEscape(isSidebarOpen, closeSidebar)
|
|
19
23
|
|
|
20
24
|
provide('close-sidebar', closeSidebar)
|
|
@@ -22,9 +26,17 @@ provide('close-sidebar', closeSidebar)
|
|
|
22
26
|
|
|
23
27
|
<template>
|
|
24
28
|
<div class="Layout">
|
|
29
|
+
<slot name="layout-top" />
|
|
25
30
|
<VPSkipLink />
|
|
26
31
|
<VPBackdrop class="backdrop" :show="isSidebarOpen" @click="closeSidebar" />
|
|
27
|
-
<VPNav
|
|
32
|
+
<VPNav>
|
|
33
|
+
<template #nav-bar-title-before><slot name="nav-bar-title-before" /></template>
|
|
34
|
+
<template #nav-bar-title-after><slot name="nav-bar-title-after" /></template>
|
|
35
|
+
<template #nav-bar-content-before><slot name="nav-bar-content-before" /></template>
|
|
36
|
+
<template #nav-bar-content-after><slot name="nav-bar-content-after" /></template>
|
|
37
|
+
<template #nav-screen-content-before><slot name="nav-screen-content-before" /></template>
|
|
38
|
+
<template #nav-screen-content-after><slot name="nav-screen-content-after" /></template>
|
|
39
|
+
</VPNav>
|
|
28
40
|
<VPLocalNav :open="isSidebarOpen" @open-menu="openSidebar" />
|
|
29
41
|
<VPSidebar :open="isSidebarOpen" />
|
|
30
42
|
|
|
@@ -34,6 +46,7 @@ provide('close-sidebar', closeSidebar)
|
|
|
34
46
|
<template #home-features-before><slot name="home-features-before" /></template>
|
|
35
47
|
<template #home-features-after><slot name="home-features-after" /></template>
|
|
36
48
|
|
|
49
|
+
<template #doc-footer-before><slot name="doc-footer-before" /></template>
|
|
37
50
|
<template #doc-before><slot name="doc-before" /></template>
|
|
38
51
|
<template #doc-after><slot name="doc-after" /></template>
|
|
39
52
|
|
|
@@ -46,6 +59,7 @@ provide('close-sidebar', closeSidebar)
|
|
|
46
59
|
</VPContent>
|
|
47
60
|
|
|
48
61
|
<VPFooter />
|
|
62
|
+
<slot name="layout-bottom" />
|
|
49
63
|
</div>
|
|
50
64
|
</template>
|
|
51
65
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
2
3
|
import docsearch from '@docsearch/js'
|
|
3
|
-
import { DocSearchHit } from '@docsearch/react/dist/esm/types'
|
|
4
4
|
import { onMounted } from 'vue'
|
|
5
5
|
import { useRouter, useRoute, useData } from 'vitepress'
|
|
6
|
-
import { DefaultTheme } from '../config'
|
|
7
6
|
|
|
8
7
|
const router = useRouter()
|
|
9
8
|
const route = useRoute()
|
|
@@ -52,7 +51,7 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
|
|
|
52
51
|
}
|
|
53
52
|
},
|
|
54
53
|
|
|
55
|
-
transformItems(items:
|
|
54
|
+
transformItems(items: any[]) {
|
|
56
55
|
return items.map((item) => {
|
|
57
56
|
return Object.assign({}, item, {
|
|
58
57
|
url: getRelativePath(item.url)
|
|
@@ -60,44 +59,14 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
|
|
|
60
59
|
})
|
|
61
60
|
},
|
|
62
61
|
|
|
63
|
-
hitComponent({ hit, children }: { hit:
|
|
64
|
-
const relativeHit = hit.url.startsWith('http')
|
|
65
|
-
? getRelativePath(hit.url as string)
|
|
66
|
-
: hit.url
|
|
67
|
-
|
|
62
|
+
hitComponent({ hit, children }: { hit: any; children: any }) {
|
|
68
63
|
return {
|
|
69
64
|
__v: null,
|
|
70
65
|
type: 'a',
|
|
71
66
|
ref: undefined,
|
|
72
67
|
constructor: undefined,
|
|
73
68
|
key: undefined,
|
|
74
|
-
|
|
75
|
-
props: {
|
|
76
|
-
href: hit.url,
|
|
77
|
-
|
|
78
|
-
onClick(event: MouseEvent) {
|
|
79
|
-
if (isSpecialClick(event)) {
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// we rely on the native link scrolling when user is already on
|
|
84
|
-
// the right anchor because Router doesn't support duplicated
|
|
85
|
-
// history entries.
|
|
86
|
-
if (route.path === relativeHit) {
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// if the hits goes to another page, we prevent the native link
|
|
91
|
-
// behavior to leverage the Router loading feature.
|
|
92
|
-
if (route.path !== relativeHit) {
|
|
93
|
-
event.preventDefault()
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
router.go(relativeHit)
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
children
|
|
100
|
-
}
|
|
69
|
+
props: { href: hit.url, children }
|
|
101
70
|
}
|
|
102
71
|
}
|
|
103
72
|
})
|
|
@@ -105,19 +74,8 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
|
|
|
105
74
|
docsearch(options)
|
|
106
75
|
}
|
|
107
76
|
|
|
108
|
-
function isSpecialClick(event: MouseEvent) {
|
|
109
|
-
return (
|
|
110
|
-
event.button === 1 ||
|
|
111
|
-
event.altKey ||
|
|
112
|
-
event.ctrlKey ||
|
|
113
|
-
event.metaKey ||
|
|
114
|
-
event.shiftKey
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
77
|
function getRelativePath(absoluteUrl: string) {
|
|
119
78
|
const { pathname, hash } = new URL(absoluteUrl)
|
|
120
|
-
|
|
121
79
|
return pathname + hash
|
|
122
80
|
}
|
|
123
81
|
</script>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
-
import {
|
|
3
|
+
import { normalizeLink } from '../support/utils'
|
|
4
|
+
import { EXTERNAL_URL_RE } from '../../shared'
|
|
4
5
|
|
|
5
6
|
const props = defineProps<{
|
|
6
7
|
tag?: string
|
|
@@ -15,7 +16,7 @@ const classes = computed(() => [
|
|
|
15
16
|
props.theme ?? 'brand'
|
|
16
17
|
])
|
|
17
18
|
|
|
18
|
-
const isExternal = computed(() => props.href &&
|
|
19
|
+
const isExternal = computed(() => props.href && EXTERNAL_URL_RE.test(props.href))
|
|
19
20
|
|
|
20
21
|
const component = computed(() => {
|
|
21
22
|
if (props.tag) {
|
|
@@ -31,9 +32,9 @@ const component = computed(() => {
|
|
|
31
32
|
:is="component"
|
|
32
33
|
class="VPButton"
|
|
33
34
|
:class="classes"
|
|
34
|
-
:href="href ?
|
|
35
|
+
:href="href ? normalizeLink(href) : undefined"
|
|
35
36
|
:target="isExternal ? '_blank' : undefined"
|
|
36
|
-
:rel="isExternal ? '
|
|
37
|
+
:rel="isExternal ? 'noreferrer' : undefined"
|
|
37
38
|
>
|
|
38
39
|
{{ text }}
|
|
39
40
|
</component>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { useRoute, useData } from 'vitepress'
|
|
3
3
|
import { useCopyCode } from '../composables/copy-code'
|
|
4
4
|
import { useSidebar } from '../composables/sidebar'
|
|
5
|
-
import
|
|
5
|
+
import Theme from '/@theme/index'
|
|
6
6
|
import VPPage from './VPPage.vue'
|
|
7
7
|
import VPHome from './VPHome.vue'
|
|
8
8
|
import VPDoc from './VPDoc.vue'
|
|
@@ -11,6 +11,8 @@ const route = useRoute()
|
|
|
11
11
|
const { frontmatter } = useData()
|
|
12
12
|
const { hasSidebar } = useSidebar()
|
|
13
13
|
|
|
14
|
+
const NotFound = Theme.NotFound || (() => '404 Not Found')
|
|
15
|
+
|
|
14
16
|
useCopyCode()
|
|
15
17
|
</script>
|
|
16
18
|
|
|
@@ -35,6 +37,7 @@ useCopyCode()
|
|
|
35
37
|
</VPHome>
|
|
36
38
|
|
|
37
39
|
<VPDoc v-else>
|
|
40
|
+
<template #doc-footer-before><slot name="doc-footer-before" /></template>
|
|
38
41
|
<template #doc-before><slot name="doc-before" /></template>
|
|
39
42
|
<template #doc-after><slot name="doc-after" /></template>
|
|
40
43
|
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
2
3
|
import { useRoute } from 'vitepress'
|
|
3
4
|
import { useSidebar } from '../composables/sidebar'
|
|
4
5
|
import VPDocAside from './VPDocAside.vue'
|
|
5
6
|
import VPDocFooter from './VPDocFooter.vue'
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
-
const { hasSidebar } = useSidebar()
|
|
8
|
+
const route = useRoute()
|
|
9
|
+
const { hasSidebar, hasAside } = useSidebar()
|
|
9
10
|
|
|
10
|
-
const pageName =
|
|
11
|
+
const pageName = computed(() =>
|
|
12
|
+
route.path.replace(/[./]+/g, '_').replace(/_html$/, '')
|
|
13
|
+
)
|
|
11
14
|
</script>
|
|
12
15
|
|
|
13
16
|
<template>
|
|
14
|
-
<div
|
|
17
|
+
<div
|
|
18
|
+
class="VPDoc"
|
|
19
|
+
:class="{ 'has-sidebar': hasSidebar, 'has-aside': hasAside }"
|
|
20
|
+
>
|
|
15
21
|
<div class="container">
|
|
16
|
-
<div class="aside">
|
|
22
|
+
<div v-if="hasAside" class="aside">
|
|
17
23
|
<div class="aside-curtain" />
|
|
18
24
|
<div class="aside-container">
|
|
19
25
|
<div class="aside-content">
|
|
@@ -32,13 +38,11 @@ const pageName = path.replace(/[./]+/g, '_').replace(/_html$/, '')
|
|
|
32
38
|
<div class="content">
|
|
33
39
|
<div class="content-container">
|
|
34
40
|
<slot name="doc-before" />
|
|
35
|
-
|
|
36
41
|
<main class="main">
|
|
37
42
|
<Content class="vp-doc" :class="pageName" />
|
|
38
43
|
</main>
|
|
39
|
-
|
|
44
|
+
<slot name="doc-footer-before" />
|
|
40
45
|
<VPDocFooter />
|
|
41
|
-
|
|
42
46
|
<slot name="doc-after" />
|
|
43
47
|
</div>
|
|
44
48
|
</div>
|
|
@@ -167,26 +171,9 @@ const pageName = path.replace(/[./]+/g, '_').replace(/_html$/, '')
|
|
|
167
171
|
|
|
168
172
|
.content-container {
|
|
169
173
|
margin: 0 auto;
|
|
170
|
-
max-width: 688px;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.edit-link {
|
|
174
|
-
margin: 0 0 32px;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.edit-link .vt-link {
|
|
178
|
-
font-size: 14px;
|
|
179
|
-
color: var(--vt-c-brand);
|
|
180
|
-
font-weight: 500;
|
|
181
174
|
}
|
|
182
175
|
|
|
183
|
-
.
|
|
184
|
-
width:
|
|
185
|
-
height: 18px;
|
|
186
|
-
color: var(--vt-c-brand);
|
|
187
|
-
display: inline-block;
|
|
188
|
-
margin-right: 8px;
|
|
189
|
-
position: relative;
|
|
190
|
-
top: -1px;
|
|
176
|
+
.VPDoc.has-aside .content-container {
|
|
177
|
+
max-width: 688px;
|
|
191
178
|
}
|
|
192
179
|
</style>
|
|
@@ -22,7 +22,9 @@ const resolvedHeaders = computed(() => {
|
|
|
22
22
|
|
|
23
23
|
function handleClick({ target: el }: Event) {
|
|
24
24
|
const id = '#' + (el as HTMLAnchorElement).href!.split('#')[1]
|
|
25
|
-
const heading = document.querySelector(
|
|
25
|
+
const heading = document.querySelector(
|
|
26
|
+
decodeURIComponent(id)
|
|
27
|
+
) as HTMLAnchorElement
|
|
26
28
|
heading?.focus()
|
|
27
29
|
}
|
|
28
30
|
</script>
|
|
@@ -13,15 +13,21 @@ const { theme, page, frontmatter } = useData()
|
|
|
13
13
|
const editLink = useEditLink()
|
|
14
14
|
const control = usePrevNext()
|
|
15
15
|
|
|
16
|
+
const hasEditLink = computed(() => {
|
|
17
|
+
return theme.value.editLink && frontmatter.value.editLink !== false
|
|
18
|
+
})
|
|
16
19
|
const hasLastUpdated = computed(() => {
|
|
17
20
|
return page.value.lastUpdated && frontmatter.value.lastUpdated !== false
|
|
18
21
|
})
|
|
22
|
+
const showFooter = computed(() => {
|
|
23
|
+
return hasEditLink.value || hasLastUpdated.value || control.value.prev || control.value.next
|
|
24
|
+
})
|
|
19
25
|
</script>
|
|
20
26
|
|
|
21
27
|
<template>
|
|
22
|
-
<footer v-if="
|
|
23
|
-
<div class="edit-info">
|
|
24
|
-
<div v-if="
|
|
28
|
+
<footer v-if="showFooter" class="VPDocFooter">
|
|
29
|
+
<div v-if="hasEditLink || hasLastUpdated" class="edit-info">
|
|
30
|
+
<div v-if="hasEditLink" class="edit-link">
|
|
25
31
|
<VPLink class="edit-link-button" :href="editLink.url" :no-icon="true">
|
|
26
32
|
<VPIconEdit class="edit-link-icon" />
|
|
27
33
|
{{ editLink.text }}
|
|
@@ -33,16 +39,16 @@ const hasLastUpdated = computed(() => {
|
|
|
33
39
|
</div>
|
|
34
40
|
</div>
|
|
35
41
|
|
|
36
|
-
<div class="prev-next">
|
|
42
|
+
<div v-if="control.prev || control.next" class="prev-next">
|
|
37
43
|
<div class="pager">
|
|
38
44
|
<a v-if="control.prev" class="pager-link prev" :href="normalizeLink(control.prev.link)">
|
|
39
|
-
<span class="desc">Previous page</span>
|
|
45
|
+
<span class="desc">{{ theme.docFooter?.prev ?? 'Previous page' }}</span>
|
|
40
46
|
<span class="title">{{ control.prev.text }} </span>
|
|
41
47
|
</a>
|
|
42
48
|
</div>
|
|
43
49
|
<div class="pager" :class="{ 'has-prev': control.prev }">
|
|
44
50
|
<a v-if="control.next" class="pager-link next" :href="normalizeLink(control.next.link)">
|
|
45
|
-
<span class="desc">Next page</span>
|
|
51
|
+
<span class="desc">{{ theme.docFooter?.next ?? 'Next page' }}</span>
|
|
46
52
|
<span class="title">{{ control.next.text }}</span>
|
|
47
53
|
</a>
|
|
48
54
|
</div>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, watchEffect, onMounted } from 'vue'
|
|
2
|
+
import { ref, computed, watchEffect, onMounted } from 'vue'
|
|
3
3
|
import { useData } from 'vitepress'
|
|
4
4
|
|
|
5
5
|
const { theme, page } = useData()
|
|
6
6
|
|
|
7
|
-
const date = new Date(page.value.lastUpdated!)
|
|
8
|
-
const isoDatetime = date.toISOString()
|
|
7
|
+
const date = computed(() => new Date(page.value.lastUpdated!))
|
|
8
|
+
const isoDatetime = computed(() => date.value.toISOString())
|
|
9
9
|
const datetime = ref('')
|
|
10
10
|
|
|
11
11
|
// set time on mounted hook because the locale string might be different
|
|
@@ -13,7 +13,7 @@ const datetime = ref('')
|
|
|
13
13
|
// calculated at build time
|
|
14
14
|
onMounted(() => {
|
|
15
15
|
watchEffect(() => {
|
|
16
|
-
datetime.value = date.toLocaleString(window.navigator.language)
|
|
16
|
+
datetime.value = date.value.toLocaleString(window.navigator.language)
|
|
17
17
|
})
|
|
18
18
|
})
|
|
19
19
|
</script>
|
|
@@ -60,7 +60,7 @@ function onBlur() {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
.VPFlyout:hover {
|
|
63
|
-
color: var(--vp-c-
|
|
63
|
+
color: var(--vp-c-brand);
|
|
64
64
|
transition: color 0.25s;
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -72,6 +72,14 @@ function onBlur() {
|
|
|
72
72
|
fill: var(--vp-c-text-2);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
.VPFlyout.active .text {
|
|
76
|
+
color: var(--vp-c-brand);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.VPFlyout.active:hover .text {
|
|
80
|
+
color: var(--vp-c-brand-dark);
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
.VPFlyout:hover .menu,
|
|
76
84
|
.button[aria-expanded="true"] + .menu {
|
|
77
85
|
opacity: 1;
|
|
@@ -9,8 +9,8 @@ const { hasSidebar } = useSidebar()
|
|
|
9
9
|
<template>
|
|
10
10
|
<footer v-if="theme.footer" class="VPFooter" :class="{ 'has-sidebar': hasSidebar }">
|
|
11
11
|
<div class="container">
|
|
12
|
-
<p class="message"
|
|
13
|
-
<p class="copyright"
|
|
12
|
+
<p class="message" v-html="theme.footer.message"></p>
|
|
13
|
+
<p class="copyright" v-html="theme.footer.copyright"></p>
|
|
14
14
|
</div>
|
|
15
15
|
</footer>
|
|
16
16
|
</template>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
2
3
|
import VPButton from './VPButton.vue'
|
|
4
|
+
import VPImage from './VPImage.vue'
|
|
3
5
|
|
|
4
6
|
export interface HeroAction {
|
|
5
7
|
theme?: 'brand' | 'alt'
|
|
@@ -7,16 +9,11 @@ export interface HeroAction {
|
|
|
7
9
|
link: string
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export interface Image {
|
|
11
|
-
src: string
|
|
12
|
-
alt?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
12
|
defineProps<{
|
|
16
13
|
name?: string
|
|
17
14
|
text: string
|
|
18
15
|
tagline?: string
|
|
19
|
-
image?:
|
|
16
|
+
image?: DefaultTheme.ThemeableImage
|
|
20
17
|
actions?: HeroAction[]
|
|
21
18
|
}>()
|
|
22
19
|
</script>
|
|
@@ -25,7 +22,9 @@ defineProps<{
|
|
|
25
22
|
<div class="VPHero" :class="{ 'has-image': image }">
|
|
26
23
|
<div class="container">
|
|
27
24
|
<div class="main">
|
|
28
|
-
<h1 v-if="name" class="name"
|
|
25
|
+
<h1 v-if="name" class="name">
|
|
26
|
+
<span class="clip">{{ name }}</span>
|
|
27
|
+
</h1>
|
|
29
28
|
<p v-if="text" class="text">{{ text }}</p>
|
|
30
29
|
<p v-if="tagline" class="tagline">{{ tagline }}</p>
|
|
31
30
|
|
|
@@ -45,7 +44,7 @@ defineProps<{
|
|
|
45
44
|
<div v-if="image" class="image">
|
|
46
45
|
<div class="image-container">
|
|
47
46
|
<div class="image-bg" />
|
|
48
|
-
<
|
|
47
|
+
<VPImage class="image-src" :image="image" />
|
|
49
48
|
</div>
|
|
50
49
|
</div>
|
|
51
50
|
</div>
|
|
@@ -293,7 +292,7 @@ defineProps<{
|
|
|
293
292
|
}
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
.image-src {
|
|
295
|
+
:deep(.image-src) {
|
|
297
296
|
position: absolute;
|
|
298
297
|
top: 50%;
|
|
299
298
|
left: 50%;
|
|
@@ -302,13 +301,13 @@ defineProps<{
|
|
|
302
301
|
}
|
|
303
302
|
|
|
304
303
|
@media (min-width: 640px) {
|
|
305
|
-
.image-src {
|
|
304
|
+
:deep(.image-src) {
|
|
306
305
|
max-width: 256px;
|
|
307
306
|
}
|
|
308
307
|
}
|
|
309
308
|
|
|
310
309
|
@media (min-width: 960px) {
|
|
311
|
-
.image-src {
|
|
310
|
+
:deep(.image-src) {
|
|
312
311
|
max-width: 320px;
|
|
313
312
|
}
|
|
314
313
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
|
+
import { withBase } from 'vitepress'
|
|
4
|
+
|
|
5
|
+
defineProps<{
|
|
6
|
+
image: DefaultTheme.ThemeableImage
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
export default {
|
|
12
|
+
inheritAttrs: false
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<template v-if="image">
|
|
18
|
+
<img
|
|
19
|
+
v-if="typeof image === 'string' || 'src' in image"
|
|
20
|
+
class="VPImage"
|
|
21
|
+
v-bind="typeof image === 'string' ? $attrs : { ...image, ...$attrs }"
|
|
22
|
+
:src="withBase(typeof image === 'string' ? image : image.src)"
|
|
23
|
+
/>
|
|
24
|
+
<template v-else>
|
|
25
|
+
<VPImage class="dark" :image="image.dark" v-bind="$attrs" />
|
|
26
|
+
<VPImage class="light" :image="image.light" v-bind="$attrs" />
|
|
27
|
+
</template>
|
|
28
|
+
</template>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<style scoped>
|
|
32
|
+
html:not(.dark) .VPImage.dark {
|
|
33
|
+
display: none;
|
|
34
|
+
}
|
|
35
|
+
.dark .VPImage.light {
|
|
36
|
+
display: none;
|
|
37
|
+
}
|
|
38
|
+
</style>
|