vitepress 2.0.0-alpha.4 → 2.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/vitepress.js +14 -0
- package/dist/client/app/composables/copyCode.js +8 -6
- package/dist/client/app/utils.js +3 -2
- package/dist/client/shared.js +112 -25
- package/dist/client/theme-default/Layout.vue +10 -9
- package/dist/client/theme-default/NotFound.vue +1 -1
- package/dist/client/theme-default/components/VPButton.vue +2 -2
- package/dist/client/theme-default/components/VPContent.vue +3 -6
- package/dist/client/theme-default/components/VPDoc.vue +2 -2
- package/dist/client/theme-default/components/VPDocAsideOutline.vue +8 -17
- package/dist/client/theme-default/components/VPDocAsideSponsors.vue +1 -1
- package/dist/client/theme-default/components/VPDocOutlineItem.vue +5 -3
- package/dist/client/theme-default/components/VPFeature.vue +2 -2
- package/dist/client/theme-default/components/VPFlyout.vue +1 -1
- package/dist/client/theme-default/components/VPFooter.vue +2 -2
- package/dist/client/theme-default/components/VPHero.vue +4 -1
- package/dist/client/theme-default/components/VPHomeSponsors.vue +1 -1
- package/dist/client/theme-default/components/VPLocalNav.vue +7 -23
- package/dist/client/theme-default/components/VPLocalNavOutlineDropdown.vue +5 -4
- package/dist/client/theme-default/components/VPLocalSearchBox.vue +4 -0
- package/dist/client/theme-default/components/VPMenu.vue +1 -1
- package/dist/client/theme-default/components/VPMenuGroup.vue +1 -1
- package/dist/client/theme-default/components/VPNavBar.vue +3 -5
- package/dist/client/theme-default/components/VPNavBarMenu.vue +2 -2
- package/dist/client/theme-default/components/VPNavBarSearch.vue +2 -2
- package/dist/client/theme-default/components/VPNavBarTitle.vue +4 -4
- package/dist/client/theme-default/components/VPNavScreenMenu.vue +1 -1
- package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +1 -1
- package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +1 -5
- package/dist/client/theme-default/components/VPSidebar.vue +3 -3
- package/dist/client/theme-default/components/VPSidebarGroup.vue +1 -1
- package/dist/client/theme-default/components/VPSidebarItem.vue +2 -2
- package/dist/client/theme-default/components/VPSocialLinks.vue +3 -3
- package/dist/client/theme-default/components/VPTeamMembers.vue +1 -1
- package/dist/client/theme-default/composables/aside.js +2 -2
- package/dist/client/theme-default/composables/layout.js +75 -0
- package/dist/client/theme-default/composables/sidebar.js +21 -63
- package/dist/client/theme-default/styles/components/vp-code.css +2 -2
- package/dist/client/theme-default/styles/components/vp-doc.css +2 -12
- package/dist/client/theme-default/without-fonts.js +1 -2
- package/dist/node/{chunk-BBDUp32J.js → chunk-cyL7XSn2.js} +1657 -1513
- package/dist/node/cli.js +2 -2
- package/dist/node/index.d.ts +48 -19
- package/dist/node/index.js +3 -3
- package/package.json +48 -43
- package/theme.d.ts +24 -3
- package/types/default-theme.d.ts +13 -37
- package/types/shared.d.ts +29 -2
- package/dist/client/theme-default/composables/local-nav.js +0 -18
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VitePress 📝💨
|
|
2
2
|
|
|
3
|
-
[](https://github.com/vuejs/vitepress/actions/workflows/test.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/vitepress)
|
|
5
5
|
[](https://nightly.akryum.dev/vuejs/vitepress)
|
|
6
6
|
[](https://chat.vuejs.org)
|
package/bin/vitepress.js
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
|
|
4
|
+
import module from 'node:module'
|
|
5
|
+
|
|
6
|
+
// https://github.com/vitejs/vite/blob/6c8a5a27e645a182f5b03a4ed6aa726eab85993f/packages/vite/bin/vite.js#L48-L63
|
|
7
|
+
try {
|
|
8
|
+
module.enableCompileCache?.()
|
|
9
|
+
setTimeout(() => {
|
|
10
|
+
try {
|
|
11
|
+
module.flushCompileCache?.()
|
|
12
|
+
} catch {}
|
|
13
|
+
}, 10 * 1000).unref()
|
|
14
|
+
} catch {}
|
|
15
|
+
|
|
2
16
|
import('../dist/node/cli.js')
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { inBrowser } from 'vitepress';
|
|
2
|
+
const shellRE = /language-(shellscript|shell|bash|sh|zsh)/;
|
|
3
|
+
const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'].join(', ');
|
|
2
4
|
export function useCopyCode() {
|
|
3
5
|
if (inBrowser) {
|
|
4
6
|
const timeoutIdMap = new WeakMap();
|
|
@@ -6,17 +8,17 @@ export function useCopyCode() {
|
|
|
6
8
|
const el = e.target;
|
|
7
9
|
if (el.matches('div[class*="language-"] > button.copy')) {
|
|
8
10
|
const parent = el.parentElement;
|
|
9
|
-
const sibling = el.nextElementSibling?.nextElementSibling;
|
|
11
|
+
const sibling = el.nextElementSibling?.nextElementSibling; // <pre> tag
|
|
10
12
|
if (!parent || !sibling) {
|
|
11
13
|
return;
|
|
12
14
|
}
|
|
13
|
-
const isShell =
|
|
14
|
-
const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'];
|
|
15
|
+
const isShell = shellRE.test(parent.className);
|
|
15
16
|
// Clone the node and remove the ignored nodes
|
|
16
17
|
const clone = sibling.cloneNode(true);
|
|
17
|
-
clone
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
clone.querySelectorAll(ignoredNodes).forEach((node) => node.remove());
|
|
19
|
+
// remove extra newlines left after removing ignored nodes (affecting textContent because it is inside `<pre>`)
|
|
20
|
+
// doesn't affect the newlines already in the code because they are rendered as `\n<span class="line"></span>`
|
|
21
|
+
clone.innerHTML = clone.innerHTML.replace(/\n+/g, '\n');
|
|
20
22
|
let text = clone.textContent || '';
|
|
21
23
|
if (isShell) {
|
|
22
24
|
text = text.replace(/^ *(\$|>) /gm, '').trim();
|
package/dist/client/app/utils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tryOnUnmounted } from '@vueuse/core';
|
|
2
|
+
import { h, onMounted, shallowRef } from 'vue';
|
|
2
3
|
import { EXTERNAL_URL_RE, inBrowser, sanitizeFileName } from '../shared';
|
|
3
4
|
import { siteDataRef } from './data';
|
|
4
5
|
export { escapeHtml as _escapeHtml, inBrowser } from '../shared';
|
|
@@ -62,7 +63,7 @@ export let contentUpdatedCallbacks = [];
|
|
|
62
63
|
*/
|
|
63
64
|
export function onContentUpdated(fn) {
|
|
64
65
|
contentUpdatedCallbacks.push(fn);
|
|
65
|
-
|
|
66
|
+
tryOnUnmounted(() => {
|
|
66
67
|
contentUpdatedCallbacks = contentUpdatedCallbacks.filter((f) => f !== fn);
|
|
67
68
|
});
|
|
68
69
|
}
|
package/dist/client/shared.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
|
|
2
2
|
export const APPEARANCE_KEY = 'vitepress-theme-appearance';
|
|
3
|
+
export const VP_SOURCE_KEY = '[VP_SOURCE]';
|
|
4
|
+
const UnpackStackView = Symbol('stack-view:unpack');
|
|
3
5
|
const HASH_RE = /#.*$/;
|
|
4
6
|
const HASH_OR_QUERY_RE = /[?#].*$/;
|
|
5
7
|
const INDEX_OR_EXT_RE = /(?:(^|\/)index)?\.(?:md|html)$/;
|
|
@@ -42,26 +44,29 @@ export function isExternal(path) {
|
|
|
42
44
|
export function getLocaleForPath(siteData, relativePath) {
|
|
43
45
|
return (Object.keys(siteData?.locales || {}).find((key) => key !== 'root' &&
|
|
44
46
|
!isExternal(key) &&
|
|
45
|
-
isActive(relativePath,
|
|
47
|
+
isActive(relativePath, `^/${key}/`, true)) || 'root');
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
50
|
* this merges the locales data to the main data by the route
|
|
49
51
|
*/
|
|
50
52
|
export function resolveSiteDataByRoute(siteData, relativePath) {
|
|
51
53
|
const localeIndex = getLocaleForPath(siteData, relativePath);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
const { label, link, ...localeConfig } = siteData.locales[localeIndex] ?? {};
|
|
55
|
+
Object.assign(localeConfig, { localeIndex });
|
|
56
|
+
const additionalConfigs = resolveAdditionalConfig(siteData, relativePath);
|
|
57
|
+
if (inBrowser && import.meta.env?.DEV) {
|
|
58
|
+
;
|
|
59
|
+
localeConfig[VP_SOURCE_KEY] = `locale config (${localeIndex})`;
|
|
60
|
+
reportConfigLayers(relativePath, [
|
|
61
|
+
...additionalConfigs,
|
|
62
|
+
localeConfig,
|
|
63
|
+
siteData
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
const topLayer = {
|
|
67
|
+
head: mergeHead(siteData.head ?? [], localeConfig.head ?? [], ...additionalConfigs.map((data) => data.head ?? []).reverse())
|
|
68
|
+
};
|
|
69
|
+
return stackView(topLayer, ...additionalConfigs, localeConfig, siteData);
|
|
65
70
|
}
|
|
66
71
|
/**
|
|
67
72
|
* Create the page title string based on config.
|
|
@@ -90,17 +95,29 @@ function createTitleTemplate(siteTitle, template) {
|
|
|
90
95
|
}
|
|
91
96
|
return ` | ${template}`;
|
|
92
97
|
}
|
|
93
|
-
function
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
export function mergeHead(...headArrays) {
|
|
99
|
+
const merged = [];
|
|
100
|
+
const metaKeyMap = new Map();
|
|
101
|
+
for (const current of headArrays) {
|
|
102
|
+
for (const tag of current) {
|
|
103
|
+
const [type, attrs] = tag;
|
|
104
|
+
const keyAttr = Object.entries(attrs)[0];
|
|
105
|
+
if (type !== 'meta' || !keyAttr) {
|
|
106
|
+
merged.push(tag);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const key = `${keyAttr[0]}=${keyAttr[1]}`;
|
|
110
|
+
const existingIndex = metaKeyMap.get(key);
|
|
111
|
+
if (existingIndex != null) {
|
|
112
|
+
merged[existingIndex] = tag; // replace existing tag
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
metaKeyMap.set(key, merged.length);
|
|
116
|
+
merged.push(tag);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return merged;
|
|
104
121
|
}
|
|
105
122
|
// https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
|
|
106
123
|
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
|
|
@@ -150,3 +167,73 @@ export function escapeHtml(str) {
|
|
|
150
167
|
.replace(/"/g, '"')
|
|
151
168
|
.replace(/&(?![\w#]+;)/g, '&');
|
|
152
169
|
}
|
|
170
|
+
function resolveAdditionalConfig({ additionalConfig }, path) {
|
|
171
|
+
if (additionalConfig === undefined)
|
|
172
|
+
return [];
|
|
173
|
+
if (typeof additionalConfig === 'function')
|
|
174
|
+
return additionalConfig(path) ?? [];
|
|
175
|
+
const configs = [];
|
|
176
|
+
const segments = path.split('/').slice(0, -1); // remove file name
|
|
177
|
+
while (segments.length) {
|
|
178
|
+
const key = `/${segments.join('/')}/`;
|
|
179
|
+
configs.push(additionalConfig[key]);
|
|
180
|
+
segments.pop();
|
|
181
|
+
}
|
|
182
|
+
configs.push(additionalConfig['/']);
|
|
183
|
+
return configs.filter((config) => config !== undefined);
|
|
184
|
+
}
|
|
185
|
+
// This helps users to understand which configuration files are active
|
|
186
|
+
function reportConfigLayers(path, layers) {
|
|
187
|
+
const summaryTitle = `Config Layers for ${path}:`;
|
|
188
|
+
const summary = layers.map((c, i, arr) => {
|
|
189
|
+
const n = i + 1;
|
|
190
|
+
if (n === arr.length)
|
|
191
|
+
return `${n}. .vitepress/config (root)`;
|
|
192
|
+
return `${n}. ${c?.[VP_SOURCE_KEY] ?? '(Unknown Source)'}`;
|
|
193
|
+
});
|
|
194
|
+
console.debug([summaryTitle, ''.padEnd(summaryTitle.length, '='), ...summary].join('\n'));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Creates a deep, merged view of multiple objects without mutating originals.
|
|
198
|
+
* Returns a readonly proxy behaving like a merged object of the input objects.
|
|
199
|
+
* Layers are merged in descending precedence, i.e. earlier layer is on top.
|
|
200
|
+
*/
|
|
201
|
+
export function stackView(..._layers) {
|
|
202
|
+
const layers = _layers.filter((layer) => isObject(layer));
|
|
203
|
+
if (layers.length <= 1)
|
|
204
|
+
return _layers[0];
|
|
205
|
+
const allKeys = new Set(layers.flatMap((layer) => Reflect.ownKeys(layer)));
|
|
206
|
+
const allKeysArray = [...allKeys];
|
|
207
|
+
return new Proxy({}, {
|
|
208
|
+
// TODO: optimize for performance, this is a hot path
|
|
209
|
+
get(_, prop) {
|
|
210
|
+
if (prop === UnpackStackView)
|
|
211
|
+
return layers;
|
|
212
|
+
return stackView(...layers
|
|
213
|
+
.map((layer) => layer[prop])
|
|
214
|
+
.filter((v) => v !== undefined));
|
|
215
|
+
},
|
|
216
|
+
set() {
|
|
217
|
+
throw new Error('StackView is read-only and cannot be mutated.');
|
|
218
|
+
},
|
|
219
|
+
has(_, prop) {
|
|
220
|
+
return allKeys.has(prop);
|
|
221
|
+
},
|
|
222
|
+
ownKeys() {
|
|
223
|
+
return allKeysArray;
|
|
224
|
+
},
|
|
225
|
+
getOwnPropertyDescriptor(_, prop) {
|
|
226
|
+
for (const layer of layers) {
|
|
227
|
+
const descriptor = Object.getOwnPropertyDescriptor(layer, prop);
|
|
228
|
+
if (descriptor)
|
|
229
|
+
return descriptor;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
stackView.unpack = function (obj) {
|
|
235
|
+
return obj?.[UnpackStackView];
|
|
236
|
+
};
|
|
237
|
+
export function isObject(value) {
|
|
238
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
239
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { computed, provide, useSlots, watch } from 'vue'
|
|
2
|
+
import { computed, provide, useSlots } from 'vue'
|
|
4
3
|
import VPBackdrop from './components/VPBackdrop.vue'
|
|
5
4
|
import VPContent from './components/VPContent.vue'
|
|
6
5
|
import VPFooter from './components/VPFooter.vue'
|
|
@@ -9,18 +8,16 @@ import VPNav from './components/VPNav.vue'
|
|
|
9
8
|
import VPSidebar from './components/VPSidebar.vue'
|
|
10
9
|
import VPSkipLink from './components/VPSkipLink.vue'
|
|
11
10
|
import { useData } from './composables/data'
|
|
12
|
-
import {
|
|
11
|
+
import { registerWatchers } from './composables/layout'
|
|
12
|
+
import { useSidebarControl } from './composables/sidebar'
|
|
13
13
|
|
|
14
14
|
const {
|
|
15
15
|
isOpen: isSidebarOpen,
|
|
16
16
|
open: openSidebar,
|
|
17
17
|
close: closeSidebar
|
|
18
|
-
} =
|
|
18
|
+
} = useSidebarControl()
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
watch(() => route.path, closeSidebar)
|
|
22
|
-
|
|
23
|
-
useCloseSidebarOnEscape(isSidebarOpen, closeSidebar)
|
|
20
|
+
registerWatchers({ closeSidebar })
|
|
24
21
|
|
|
25
22
|
const { frontmatter } = useData()
|
|
26
23
|
|
|
@@ -31,7 +28,11 @@ provide('hero-image-slot-exists', heroImageSlotExists)
|
|
|
31
28
|
</script>
|
|
32
29
|
|
|
33
30
|
<template>
|
|
34
|
-
<div
|
|
31
|
+
<div
|
|
32
|
+
v-if="frontmatter.layout !== false"
|
|
33
|
+
class="Layout"
|
|
34
|
+
:class="frontmatter.pageClass"
|
|
35
|
+
>
|
|
35
36
|
<slot name="layout-top" />
|
|
36
37
|
<VPSkipLink />
|
|
37
38
|
<VPBackdrop class="backdrop" :show="isSidebarOpen" @click="closeSidebar" />
|
|
@@ -22,7 +22,7 @@ const { currentLang } = useLangs()
|
|
|
22
22
|
<div class="action">
|
|
23
23
|
<a
|
|
24
24
|
class="link"
|
|
25
|
-
:href="withBase(currentLang.link)"
|
|
25
|
+
:href="withBase(theme.notFound?.link ?? currentLang.link)"
|
|
26
26
|
:aria-label="theme.notFound?.linkLabel ?? 'go to home'"
|
|
27
27
|
>
|
|
28
28
|
{{ theme.notFound?.linkText ?? 'Take me home' }}
|
|
@@ -7,7 +7,7 @@ interface Props {
|
|
|
7
7
|
tag?: string
|
|
8
8
|
size?: 'medium' | 'big'
|
|
9
9
|
theme?: 'brand' | 'alt' | 'sponsor'
|
|
10
|
-
text
|
|
10
|
+
text?: string
|
|
11
11
|
href?: string
|
|
12
12
|
target?: string;
|
|
13
13
|
rel?: string;
|
|
@@ -35,7 +35,7 @@ const component = computed(() => {
|
|
|
35
35
|
:target="props.target ?? (isExternal ? '_blank' : undefined)"
|
|
36
36
|
:rel="props.rel ?? (isExternal ? 'noreferrer' : undefined)"
|
|
37
37
|
>
|
|
38
|
-
{{ text }}
|
|
38
|
+
<slot>{{ text }}</slot>
|
|
39
39
|
</component>
|
|
40
40
|
</template>
|
|
41
41
|
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import NotFound from '../NotFound.vue'
|
|
3
3
|
import { useData } from '../composables/data'
|
|
4
|
-
import {
|
|
4
|
+
import { useLayout } from '../composables/layout'
|
|
5
5
|
import VPDoc from './VPDoc.vue'
|
|
6
6
|
import VPHome from './VPHome.vue'
|
|
7
7
|
import VPPage from './VPPage.vue'
|
|
8
8
|
|
|
9
9
|
const { page, frontmatter } = useData()
|
|
10
|
-
const { hasSidebar } =
|
|
10
|
+
const { isHome, hasSidebar } = useLayout()
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<template>
|
|
14
14
|
<div
|
|
15
15
|
class="VPContent"
|
|
16
16
|
id="VPContent"
|
|
17
|
-
:class="{
|
|
18
|
-
'has-sidebar': hasSidebar,
|
|
19
|
-
'is-home': frontmatter.layout === 'home'
|
|
20
|
-
}"
|
|
17
|
+
:class="{ 'has-sidebar': hasSidebar, 'is-home': isHome }"
|
|
21
18
|
>
|
|
22
19
|
<slot name="not-found" v-if="page.isNotFound"><NotFound /></slot>
|
|
23
20
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { useRoute } from 'vitepress'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import { useData } from '../composables/data'
|
|
5
|
-
import {
|
|
5
|
+
import { useLayout } from '../composables/layout'
|
|
6
6
|
import VPDocAside from './VPDocAside.vue'
|
|
7
7
|
import VPDocFooter from './VPDocFooter.vue'
|
|
8
8
|
|
|
9
9
|
const { theme } = useData()
|
|
10
10
|
|
|
11
11
|
const route = useRoute()
|
|
12
|
-
const { hasSidebar, hasAside, leftAside } =
|
|
12
|
+
const { hasSidebar, hasAside, leftAside } = useLayout()
|
|
13
13
|
|
|
14
14
|
const pageName = computed(() =>
|
|
15
15
|
route.path.replace(/[./]+/g, '_').replace(/_html$/, '')
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { ref, shallowRef } from 'vue'
|
|
2
|
+
import { ref } from 'vue'
|
|
4
3
|
import { useData } from '../composables/data'
|
|
5
|
-
import {
|
|
6
|
-
getHeaders,
|
|
7
|
-
resolveTitle,
|
|
8
|
-
useActiveAnchor,
|
|
9
|
-
type MenuItem
|
|
10
|
-
} from '../composables/outline'
|
|
4
|
+
import { resolveTitle, useActiveAnchor } from '../composables/outline'
|
|
11
5
|
import VPDocOutlineItem from './VPDocOutlineItem.vue'
|
|
6
|
+
import { useLayout } from '../composables/layout'
|
|
12
7
|
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
const headers = shallowRef<MenuItem[]>([])
|
|
16
|
-
|
|
17
|
-
onContentUpdated(() => {
|
|
18
|
-
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
|
19
|
-
})
|
|
8
|
+
const { theme } = useData()
|
|
20
9
|
|
|
21
10
|
const container = ref()
|
|
22
11
|
const marker = ref()
|
|
23
12
|
|
|
13
|
+
const { headers, hasLocalNav } = useLayout()
|
|
14
|
+
|
|
24
15
|
useActiveAnchor(container, marker)
|
|
25
16
|
</script>
|
|
26
17
|
|
|
@@ -28,7 +19,7 @@ useActiveAnchor(container, marker)
|
|
|
28
19
|
<nav
|
|
29
20
|
aria-labelledby="doc-outline-aria-label"
|
|
30
21
|
class="VPDocAsideOutline"
|
|
31
|
-
:class="{ 'has-outline':
|
|
22
|
+
:class="{ 'has-outline': hasLocalNav }"
|
|
32
23
|
ref="container"
|
|
33
24
|
>
|
|
34
25
|
<div class="content">
|
|
@@ -43,7 +34,7 @@ useActiveAnchor(container, marker)
|
|
|
43
34
|
{{ resolveTitle(theme) }}
|
|
44
35
|
</div>
|
|
45
36
|
|
|
46
|
-
<VPDocOutlineItem :headers
|
|
37
|
+
<VPDocOutlineItem :headers :root="true" />
|
|
47
38
|
</div>
|
|
48
39
|
</nav>
|
|
49
40
|
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
3
3
|
|
|
4
4
|
defineProps<{
|
|
5
|
-
headers:
|
|
5
|
+
headers: DefaultTheme.OutlineItem[]
|
|
6
6
|
root?: boolean
|
|
7
7
|
}>()
|
|
8
8
|
|
|
@@ -16,7 +16,9 @@ function onClick({ target: el }: Event) {
|
|
|
16
16
|
<template>
|
|
17
17
|
<ul class="VPDocOutlineItem" :class="root ? 'root' : 'nested'">
|
|
18
18
|
<li v-for="{ children, link, title } in headers">
|
|
19
|
-
<a class="outline-link" :href="link" @click="onClick" :title
|
|
19
|
+
<a class="outline-link" :href="link" @click="onClick" :title>
|
|
20
|
+
{{ title }}
|
|
21
|
+
</a>
|
|
20
22
|
<template v-if="children?.length">
|
|
21
23
|
<VPDocOutlineItem :headers="children" />
|
|
22
24
|
</template>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useData } from '../composables/data'
|
|
3
|
-
import {
|
|
3
|
+
import { useLayout } from '../composables/layout'
|
|
4
4
|
|
|
5
5
|
const { theme, frontmatter } = useData()
|
|
6
|
-
const { hasSidebar } =
|
|
6
|
+
const { hasSidebar } = useLayout()
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
@@ -57,7 +57,7 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
|
|
|
57
57
|
<div class="image-container">
|
|
58
58
|
<div class="image-bg" />
|
|
59
59
|
<slot name="home-hero-image">
|
|
60
|
-
<VPImage v-if="image" class="image-src" :image
|
|
60
|
+
<VPImage v-if="image" class="image-src" :image />
|
|
61
61
|
</slot>
|
|
62
62
|
</div>
|
|
63
63
|
</div>
|
|
@@ -322,6 +322,9 @@ const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
|
|
|
322
322
|
left: 50%;
|
|
323
323
|
max-width: 192px;
|
|
324
324
|
max-height: 192px;
|
|
325
|
+
width: 100%;
|
|
326
|
+
height: 100%;
|
|
327
|
+
object-fit: contain;
|
|
325
328
|
/*rtl:ignore*/
|
|
326
329
|
transform: translate(-50%, -50%);
|
|
327
330
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { useWindowScroll } from '@vueuse/core'
|
|
3
|
-
import { onContentUpdated } from 'vitepress'
|
|
4
3
|
import { computed, onMounted, ref } from 'vue'
|
|
5
4
|
import { useData } from '../composables/data'
|
|
6
|
-
import {
|
|
7
|
-
import { getHeaders } from '../composables/outline'
|
|
8
|
-
import { useSidebar } from '../composables/sidebar'
|
|
5
|
+
import { useLayout } from '../composables/layout'
|
|
9
6
|
import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue'
|
|
10
7
|
|
|
11
8
|
defineProps<{
|
|
@@ -16,9 +13,8 @@ defineEmits<{
|
|
|
16
13
|
(e: 'open-menu'): void
|
|
17
14
|
}>()
|
|
18
15
|
|
|
19
|
-
const { theme
|
|
20
|
-
const { hasSidebar } =
|
|
21
|
-
const { headers } = useLocalNav()
|
|
16
|
+
const { theme } = useData()
|
|
17
|
+
const { isHome, hasSidebar, headers, hasLocalNav } = useLayout()
|
|
22
18
|
const { y } = useWindowScroll()
|
|
23
19
|
|
|
24
20
|
const navHeight = ref(0)
|
|
@@ -31,31 +27,19 @@ onMounted(() => {
|
|
|
31
27
|
)
|
|
32
28
|
})
|
|
33
29
|
|
|
34
|
-
onContentUpdated(() => {
|
|
35
|
-
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const empty = computed(() => {
|
|
39
|
-
return headers.value.length === 0
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
const emptyAndNoSidebar = computed(() => {
|
|
43
|
-
return empty.value && !hasSidebar.value
|
|
44
|
-
})
|
|
45
|
-
|
|
46
30
|
const classes = computed(() => {
|
|
47
31
|
return {
|
|
48
32
|
VPLocalNav: true,
|
|
49
33
|
'has-sidebar': hasSidebar.value,
|
|
50
|
-
empty:
|
|
51
|
-
fixed:
|
|
34
|
+
empty: !hasLocalNav.value,
|
|
35
|
+
fixed: !hasLocalNav.value && !hasSidebar.value,
|
|
52
36
|
}
|
|
53
37
|
})
|
|
54
38
|
</script>
|
|
55
39
|
|
|
56
40
|
<template>
|
|
57
41
|
<div
|
|
58
|
-
v-if="
|
|
42
|
+
v-if="!isHome && (hasLocalNav || hasSidebar || y >= navHeight)"
|
|
59
43
|
:class="classes"
|
|
60
44
|
>
|
|
61
45
|
<div class="container">
|
|
@@ -72,7 +56,7 @@ const classes = computed(() => {
|
|
|
72
56
|
</span>
|
|
73
57
|
</button>
|
|
74
58
|
|
|
75
|
-
<VPLocalNavOutlineDropdown :headers
|
|
59
|
+
<VPLocalNavOutlineDropdown :headers :navHeight />
|
|
76
60
|
</div>
|
|
77
61
|
</div>
|
|
78
62
|
</template>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { onKeyStroke } from '@vueuse/core'
|
|
3
3
|
import { onContentUpdated } from 'vitepress'
|
|
4
|
+
import type { DefaultTheme } from 'vitepress/theme'
|
|
4
5
|
import { nextTick, ref, watch } from 'vue'
|
|
5
6
|
import { useData } from '../composables/data'
|
|
6
|
-
import { resolveTitle
|
|
7
|
+
import { resolveTitle } from '../composables/outline'
|
|
7
8
|
import VPDocOutlineItem from './VPDocOutlineItem.vue'
|
|
8
9
|
|
|
9
10
|
const props = defineProps<{
|
|
10
|
-
headers:
|
|
11
|
+
headers: DefaultTheme.OutlineItem[]
|
|
11
12
|
navHeight: number
|
|
12
13
|
}>()
|
|
13
14
|
|
|
@@ -83,7 +84,7 @@ function scrollToTop() {
|
|
|
83
84
|
</a>
|
|
84
85
|
</div>
|
|
85
86
|
<div class="outline">
|
|
86
|
-
<VPDocOutlineItem :headers
|
|
87
|
+
<VPDocOutlineItem :headers />
|
|
87
88
|
</div>
|
|
88
89
|
</div>
|
|
89
90
|
</Transition>
|
|
@@ -125,7 +126,7 @@ function scrollToTop() {
|
|
|
125
126
|
vertical-align: middle;
|
|
126
127
|
margin-left: 2px;
|
|
127
128
|
font-size: 14px;
|
|
128
|
-
transform: rotate(0)/*rtl:rotate(180deg)*/;
|
|
129
|
+
transform: rotate(0) /*rtl:rotate(180deg)*/;
|
|
129
130
|
transition: transform 0.25s;
|
|
130
131
|
}
|
|
131
132
|
|
|
@@ -11,7 +11,7 @@ defineProps<{
|
|
|
11
11
|
<div class="VPMenu">
|
|
12
12
|
<div v-if="items" class="items">
|
|
13
13
|
<template v-for="item in items" :key="JSON.stringify(item)">
|
|
14
|
-
<VPMenuLink v-if="'link' in item" :item
|
|
14
|
+
<VPMenuLink v-if="'link' in item" :item />
|
|
15
15
|
<component
|
|
16
16
|
v-else-if="'component' in item"
|
|
17
17
|
:is="item.component"
|