vitepress 2.0.0-alpha.18 → 2.0.0-alpha.19

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.
Files changed (64) hide show
  1. package/dist/client/app/components/Content.js +1 -1
  2. package/dist/client/app/data.js +4 -14
  3. package/dist/client/app/utils.js +1 -1
  4. package/dist/client/index.d.ts +35 -179
  5. package/dist/client/index.js +4 -1
  6. package/dist/client/shared.js +16 -14
  7. package/dist/client/theme-default/components/VPCarbonAds.vue +3 -3
  8. package/dist/client/theme-default/components/VPDoc.vue +0 -1
  9. package/dist/client/theme-default/components/VPDocFooter.vue +4 -0
  10. package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +1 -1
  11. package/dist/client/theme-default/components/VPFeatures.vue +4 -4
  12. package/dist/client/theme-default/components/VPHomeContent.vue +1 -0
  13. package/dist/client/theme-default/components/VPImage.vue +1 -1
  14. package/dist/client/theme-default/components/VPLink.vue +4 -2
  15. package/dist/client/theme-default/components/VPLocalNavOutlineDropdown.vue +2 -1
  16. package/dist/client/theme-default/components/VPLocalSearchBox.vue +2 -3
  17. package/dist/client/theme-default/components/VPMenu.vue +4 -4
  18. package/dist/client/theme-default/components/VPMenuLink.vue +8 -7
  19. package/dist/client/theme-default/components/VPNavBarExtra.vue +9 -6
  20. package/dist/client/theme-default/components/VPNavBarMenu.vue +16 -10
  21. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +11 -5
  22. package/dist/client/theme-default/components/VPNavBarMenuLink.vue +8 -7
  23. package/dist/client/theme-default/components/VPNavBarTranslations.vue +9 -6
  24. package/dist/client/theme-default/components/VPNavScreenMenu.vue +16 -14
  25. package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +4 -4
  26. package/dist/client/theme-default/components/VPNavScreenMenuGroupLink.vue +8 -7
  27. package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +5 -1
  28. package/dist/client/theme-default/components/VPNavScreenMenuLink.vue +8 -7
  29. package/dist/client/theme-default/components/VPNavScreenTranslations.vue +4 -1
  30. package/dist/client/theme-default/components/VPSidebarItem.vue +4 -4
  31. package/dist/client/theme-default/components/VPSocialLink.vue +2 -2
  32. package/dist/client/theme-default/components/VPSocialLinks.vue +19 -11
  33. package/dist/client/theme-default/components/VPSponsorsGrid.vue +4 -4
  34. package/dist/client/theme-default/components/VPTeamMembers.vue +15 -4
  35. package/dist/client/theme-default/composables/flyout.js +1 -1
  36. package/dist/client/theme-default/composables/langs.js +34 -14
  37. package/dist/client/theme-default/composables/layout.js +1 -1
  38. package/dist/client/theme-default/composables/outline.js +17 -2
  39. package/dist/client/theme-default/composables/prev-next.js +19 -13
  40. package/dist/client/theme-default/composables/sidebar.js +27 -20
  41. package/dist/client/theme-default/fonts/inter-italic-latin.woff2 +0 -0
  42. package/dist/client/theme-default/fonts/inter-italic-symbols.woff2 +0 -0
  43. package/dist/client/theme-default/fonts/inter-roman-latin.woff2 +0 -0
  44. package/dist/client/theme-default/fonts/inter-roman-symbols.woff2 +0 -0
  45. package/dist/client/theme-default/index.js +1 -0
  46. package/dist/client/theme-default/styles/base.css +211 -157
  47. package/dist/client/theme-default/styles/components/custom-block.css +6 -1
  48. package/dist/client/theme-default/styles/components/vp-doc.css +53 -4
  49. package/dist/client/theme-default/styles/components/vp-sponsor.css +8 -0
  50. package/dist/client/theme-default/styles/docsearch.css +0 -4
  51. package/dist/client/theme-default/styles/fonts.css +151 -141
  52. package/dist/client/theme-default/styles/vars.css +2 -34
  53. package/dist/client/theme-default/support/reactivity.js +2 -2
  54. package/dist/client/theme-default/support/sidebar.js +12 -8
  55. package/dist/client/theme-default/support/utils.js +7 -0
  56. package/dist/node/{chunk-Cne7GbZY.js → chunk-B0BRqWJx.js} +3035 -4956
  57. package/dist/node/cli.js +45 -58
  58. package/dist/node/index.d.ts +723 -1103
  59. package/dist/node/index.js +24 -13
  60. package/dist/web-types.json +75 -0
  61. package/package.json +50 -48
  62. package/theme.d.ts +7 -1
  63. package/types/default-theme.d.ts +2 -24
  64. package/types/shared.d.ts +401 -47
@@ -8,8 +8,8 @@ export const Content = defineComponent({
8
8
  as: { type: [Object, String], default: 'div' }
9
9
  },
10
10
  setup(props) {
11
- const route = useRoute();
12
11
  const { frontmatter, site } = useData();
12
+ const route = useRoute();
13
13
  watch(frontmatter, runCbs, { deep: true, flush: 'post' });
14
14
  return () => h(props.as, site.value.contentProps ?? { style: { position: 'relative' } }, [
15
15
  route.component
@@ -1,13 +1,13 @@
1
1
  import siteData from '@siteData';
2
2
  import { useDark, usePreferredDark } from '@vueuse/core';
3
- import { computed, inject, readonly, ref, shallowRef, watch } from 'vue';
4
- import { APPEARANCE_KEY, createTitle, inBrowser, resolveSiteDataByRoute } from '../shared';
3
+ import { computed, inject, readonly, ref, shallowRef } from 'vue';
4
+ import { APPEARANCE_KEY, createTitle, resolveSiteDataByRoute } from '../shared';
5
5
  export const dataSymbol = Symbol();
6
6
  // site data is a singleton
7
7
  export const siteDataRef = shallowRef(readonly(siteData));
8
8
  // per-app data
9
9
  export function initData(route) {
10
- const site = computed(() => resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath));
10
+ const site = computed(() => resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath, route.data.filePath));
11
11
  const appearance = site.value.appearance; // fine with reactivity being lost here, config change triggers a restart
12
12
  const isDark = appearance === 'force-dark'
13
13
  ? ref(true)
@@ -20,15 +20,6 @@ export function initData(route) {
20
20
  ...(typeof appearance === 'object' ? appearance : {})
21
21
  })
22
22
  : ref(false);
23
- const hashRef = ref(inBrowser ? location.hash : '');
24
- if (inBrowser) {
25
- window.addEventListener('hashchange', () => {
26
- hashRef.value = location.hash;
27
- });
28
- }
29
- watch(() => route.data, () => {
30
- hashRef.value = inBrowser ? location.hash : '';
31
- });
32
23
  return {
33
24
  site,
34
25
  theme: computed(() => site.value.themeConfig),
@@ -40,8 +31,7 @@ export function initData(route) {
40
31
  localeIndex: computed(() => site.value.localeIndex || 'root'),
41
32
  title: computed(() => createTitle(site.value, route.data)),
42
33
  description: computed(() => route.data.description || site.value.description),
43
- isDark,
44
- hash: computed(() => hashRef.value)
34
+ isDark
45
35
  };
46
36
  }
47
37
  export function useData() {
@@ -10,7 +10,7 @@ export function joinPath(base, path) {
10
10
  return `${base}${path}`.replace(/\/+/g, '/');
11
11
  }
12
12
  /**
13
- * Append base to internal (non-relative) urls
13
+ * Prepend base to internal (non-relative) urls
14
14
  */
15
15
  export function withBase(path) {
16
16
  return EXTERNAL_URL_RE.test(path) || !path.startsWith('/')
@@ -1,159 +1,7 @@
1
+ import { Route, Awaitable, SiteData, VitePressData, PageData } from '../../types/shared.js';
2
+ export { HeadConfig, Header, PageData, Route, SiteData, VitePressData } from '../../types/shared.js';
1
3
  import * as vue from 'vue';
2
- import { Ref, Component, App, InjectionKey, AsyncComponentLoader } from 'vue';
3
- import { UseDarkOptions } from '@vueuse/core';
4
-
5
- // types shared between server and client
6
-
7
-
8
- type Awaitable<T> = T | PromiseLike<T>
9
-
10
- type DeepPartial<T> =
11
- T extends Record<string, any>
12
- ? T extends
13
- | Date
14
- | RegExp
15
- | Function
16
- | ReadonlyMap<any, any>
17
- | ReadonlySet<any>
18
- | ReadonlyArray<any>
19
- ? T
20
- : { [P in keyof T]?: DeepPartial<T[P]> }
21
- : T
22
-
23
- interface PageData {
24
- relativePath: string
25
- /**
26
- * differs from relativePath in case of path rewrites
27
- * empty string if the page is virtual (e.g. 404 page)
28
- */
29
- filePath: string
30
- title: string
31
- titleTemplate?: string | boolean
32
- description: string
33
- headers: Header[]
34
- frontmatter: Record<string, any>
35
- params?: Record<string, any>
36
- isNotFound?: boolean
37
- lastUpdated?: number
38
- }
39
-
40
- interface Header {
41
- /**
42
- * The level of the header
43
- *
44
- * `1` to `6` for `<h1>` to `<h6>`
45
- */
46
- level: number
47
- /**
48
- * The title of the header
49
- */
50
- title: string
51
- /**
52
- * The slug of the header
53
- *
54
- * Typically the `id` attr of the header anchor
55
- */
56
- slug: string
57
- /**
58
- * Link of the header
59
- *
60
- * Typically using `#${slug}` as the anchor hash
61
- */
62
- link: string
63
- /**
64
- * The children of the header
65
- */
66
- children: Header[]
67
- }
68
-
69
- interface SiteData<ThemeConfig = any> {
70
- base: string
71
- cleanUrls?: boolean
72
- lang: string
73
- dir: string
74
- title: string
75
- titleTemplate?: string | boolean
76
- description: string
77
- head: HeadConfig[]
78
- appearance:
79
- | boolean
80
- | 'dark'
81
- | 'force-dark'
82
- | 'force-auto'
83
- | (Omit<UseDarkOptions, 'initialValue'> & { initialValue?: 'dark' })
84
- themeConfig: ThemeConfig
85
- locales: LocaleConfig<ThemeConfig>
86
- localeIndex?: string
87
- contentProps?: Record<string, any>
88
- router: {
89
- prefetchLinks: boolean
90
- }
91
- additionalConfig?:
92
- AdditionalConfigDict<ThemeConfig> | AdditionalConfigLoader<ThemeConfig>
93
- }
94
-
95
- interface VitePressData<T = any> {
96
- /**
97
- * Site-level metadata
98
- */
99
- site: Ref<SiteData<T>>
100
- /**
101
- * themeConfig from .vitepress/config.js
102
- */
103
- theme: Ref<T>
104
- /**
105
- * Page-level metadata
106
- */
107
- page: Ref<PageData>
108
- /**
109
- * page frontmatter data
110
- */
111
- frontmatter: Ref<PageData['frontmatter']>
112
- /**
113
- * dynamic route params
114
- */
115
- params: Ref<PageData['params']>
116
- title: Ref<string>
117
- description: Ref<string>
118
- lang: Ref<string>
119
- dir: Ref<string>
120
- localeIndex: Ref<string>
121
- isDark: Ref<boolean>
122
- /**
123
- * Current location hash
124
- */
125
- hash: Ref<string>
126
- }
127
-
128
- type HeadConfig =
129
- [string, Record<string, string>] | [string, Record<string, string>, string]
130
-
131
- interface LocaleSpecificConfig<ThemeConfig = any> {
132
- lang?: string
133
- dir?: string
134
- title?: string
135
- titleTemplate?: string | boolean
136
- description?: string
137
- head?: HeadConfig[]
138
- themeConfig?: DeepPartial<ThemeConfig>
139
- }
140
-
141
- type LocaleConfig<ThemeConfig = any> = Record<
142
- string,
143
- LocaleSpecificConfig<ThemeConfig> & { label: string; link?: string }
144
- >
145
-
146
- type AdditionalConfig<ThemeConfig = any> =
147
- LocaleSpecificConfig<ThemeConfig>
148
-
149
- type AdditionalConfigDict<ThemeConfig = any> = Record<
150
- string,
151
- AdditionalConfig<ThemeConfig>
152
- >
153
-
154
- type AdditionalConfigLoader<ThemeConfig = any> = (
155
- relativePath: string
156
- ) => AdditionalConfig<ThemeConfig>[] | void
4
+ import { App, Ref, Component, InjectionKey, AsyncComponentLoader } from 'vue';
157
5
 
158
6
  declare const inBrowser: boolean;
159
7
  /**
@@ -161,13 +9,6 @@ declare const inBrowser: boolean;
161
9
  */
162
10
  declare function escapeHtml(str: string): string;
163
11
 
164
- interface Route {
165
- path: string;
166
- hash: string;
167
- query: string;
168
- data: PageData;
169
- component: Component | null;
170
- }
171
12
  interface Router {
172
13
  /**
173
14
  * Current route.
@@ -220,12 +61,32 @@ interface Theme {
220
61
  NotFound?: Component;
221
62
  }
222
63
 
64
+ declare const ClientOnly: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
65
+ [key: string]: any;
66
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
67
+
68
+ declare const Content: vue.DefineComponent<vue.ExtractPropTypes<{
69
+ as: {
70
+ type: (ObjectConstructor | StringConstructor)[];
71
+ default: string;
72
+ };
73
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
74
+ [key: string]: any;
75
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
76
+ as: {
77
+ type: (ObjectConstructor | StringConstructor)[];
78
+ default: string;
79
+ };
80
+ }>> & Readonly<{}>, {
81
+ as: string | Record<string, any>;
82
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
83
+
223
84
  declare const dataSymbol: InjectionKey<VitePressData>;
224
85
 
225
86
  declare function useData<T = any>(): VitePressData<T>;
226
87
 
227
88
  /**
228
- * Append base to internal (non-relative) urls
89
+ * Prepend base to internal (non-relative) urls
229
90
  */
230
91
  declare function withBase(path: string): string;
231
92
  /**
@@ -239,20 +100,15 @@ declare function defineClientComponent(loader: AsyncComponentLoader, args?: any[
239
100
  }> | null;
240
101
  };
241
102
 
242
- declare const Content: vue.DefineComponent<vue.ExtractPropTypes<{
243
- as: {
244
- type: (ObjectConstructor | StringConstructor)[];
245
- default: string;
246
- };
247
- }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
248
- [key: string]: any;
249
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
250
- as: {
251
- type: (ObjectConstructor | StringConstructor)[];
252
- default: string;
253
- };
254
- }>> & Readonly<{}>, {
255
- as: string | Record<string, any>;
256
- }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
103
+ declare module 'vue' {
104
+ interface GlobalComponents {
105
+ ClientOnly: typeof ClientOnly;
106
+ Content: typeof Content;
107
+ }
108
+ interface ComponentCustomProperties {
109
+ $frontmatter: PageData['frontmatter'];
110
+ $params: PageData['params'];
111
+ }
112
+ }
257
113
 
258
- export { Content, type EnhanceAppContext, type HeadConfig, type Header, type PageData, type Route, type Router, type SiteData, type Theme, type VitePressData, escapeHtml as _escapeHtml, dataSymbol, defineClientComponent, inBrowser, onContentUpdated, useData, useRoute, useRouter, withBase };
114
+ export { ClientOnly, Content, type EnhanceAppContext, type Router, type Theme, escapeHtml as _escapeHtml, dataSymbol, defineClientComponent, inBrowser, onContentUpdated, useData, useRoute, useRouter, withBase };
@@ -1,9 +1,12 @@
1
1
  // exports in this file are exposed to themes and md files via 'vitepress'
2
2
  // so the user can do `import { useRoute, useData } from 'vitepress'`
3
+ // components
4
+ import { ClientOnly } from './app/components/ClientOnly';
5
+ import { Content } from './app/components/Content';
3
6
  // composables
4
7
  export { dataSymbol, useData } from './app/data';
5
8
  export { useRoute, useRouter } from './app/router';
6
9
  // utilities
7
10
  export { _escapeHtml, defineClientComponent, inBrowser, onContentUpdated, withBase } from './app/utils';
8
11
  // components
9
- export { Content } from './app/components/Content';
12
+ export { ClientOnly, Content };
@@ -5,6 +5,11 @@ const UnpackStackView = Symbol('stack-view:unpack');
5
5
  const HASH_WITHOUT_FRAGMENT_RE = /#.*?(?=:~:|$)/;
6
6
  const HASH_OR_QUERY_RE = /[?#].*$/;
7
7
  const INDEX_OR_EXT_RE = /(?:(^|\/)index)?(?:\.(?:md|html))?$/;
8
+ // https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
9
+ const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
10
+ const DRIVE_LETTER_REGEX = /^[a-z]:/i;
11
+ const KNOWN_EXTENSIONS = new Set();
12
+ const shellLangs = ['shellscript', 'shell', 'bash', 'sh', 'zsh'];
8
13
  export const inBrowser = typeof document !== 'undefined';
9
14
  export const notFoundPageData = {
10
15
  relativePath: '404.md',
@@ -16,10 +21,7 @@ export const notFoundPageData = {
16
21
  lastUpdated: 0,
17
22
  isNotFound: true
18
23
  };
19
- export function isActive(currentPath, matchPath, asRegex = false) {
20
- if (matchPath === undefined) {
21
- return false;
22
- }
24
+ export function isActive(currentPath, currentHash, matchPath, asRegex = false, skipHashCheck = false) {
23
25
  currentPath = normalize(`/${currentPath}`);
24
26
  if (asRegex) {
25
27
  return new RegExp(matchPath).test(currentPath);
@@ -27,9 +29,12 @@ export function isActive(currentPath, matchPath, asRegex = false) {
27
29
  if (normalize(matchPath) !== currentPath) {
28
30
  return false;
29
31
  }
32
+ if (skipHashCheck) {
33
+ return true;
34
+ }
30
35
  const hashMatch = matchPath.match(HASH_WITHOUT_FRAGMENT_RE);
31
36
  if (hashMatch) {
32
- return (inBrowser ? location.hash : '') === hashMatch[0];
37
+ return currentHash === hashMatch[0];
33
38
  }
34
39
  return true;
35
40
  }
@@ -44,16 +49,18 @@ export function isExternal(path) {
44
49
  export function getLocaleForPath(siteData, relativePath) {
45
50
  return (Object.keys(siteData?.locales || {}).find((key) => key !== 'root' &&
46
51
  !isExternal(key) &&
47
- isActive(relativePath, `^/${key}/`, true)) || 'root');
52
+ isActive(relativePath, '', `^/${key}/`, true)) || 'root');
48
53
  }
49
54
  /**
50
55
  * this merges the locales data to the main data by the route
51
56
  */
52
- export function resolveSiteDataByRoute(siteData, relativePath) {
57
+ export function resolveSiteDataByRoute(siteData, relativePath, filePath) {
53
58
  const localeIndex = getLocaleForPath(siteData, relativePath);
54
- const { label, link, ...localeConfig } = siteData.locales[localeIndex] ?? {};
59
+ const { label, link, markdown, ...localeConfig } = siteData.locales[localeIndex] ?? {};
55
60
  Object.assign(localeConfig, { localeIndex });
56
- const additionalConfigs = resolveAdditionalConfig(siteData, relativePath);
61
+ // additional configs are colocated with sources, so resolve them by the
62
+ // source path (filePath) rather than the rewritten one
63
+ const additionalConfigs = resolveAdditionalConfig(siteData, filePath || relativePath);
57
64
  if (inBrowser && import.meta.env?.DEV) {
58
65
  ;
59
66
  localeConfig[VP_SOURCE_KEY] = `locale config (${localeIndex})`;
@@ -119,9 +126,6 @@ export function mergeHead(...headArrays) {
119
126
  }
120
127
  return merged;
121
128
  }
122
- // https://github.com/rollup/rollup/blob/fec513270c6ac350072425cc045db367656c623b/src/utils/sanitizeFileName.ts
123
- const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
124
- const DRIVE_LETTER_REGEX = /^[a-z]:/i;
125
129
  export function sanitizeFileName(name) {
126
130
  const match = DRIVE_LETTER_REGEX.exec(name);
127
131
  const driveLetter = match ? match[0] : '';
@@ -134,7 +138,6 @@ export function sanitizeFileName(name) {
134
138
  export function slash(p) {
135
139
  return p.replace(/\\/g, '/');
136
140
  }
137
- const KNOWN_EXTENSIONS = new Set();
138
141
  export function treatAsHtml(filename) {
139
142
  if (KNOWN_EXTENSIONS.size === 0) {
140
143
  const extraExts = (typeof process === 'object' && process.env?.VITE_EXTRA_EXTENSIONS) ||
@@ -237,7 +240,6 @@ stackView.unpack = function (obj) {
237
240
  export function isObject(value) {
238
241
  return Object.prototype.toString.call(value) === '[object Object]';
239
242
  }
240
- const shellLangs = ['shellscript', 'shell', 'bash', 'sh', 'zsh'];
241
243
  export function isShell(lang) {
242
244
  return shellLangs.includes(lang);
243
245
  }
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
+ import { useRoute } from 'vitepress'
2
3
  import type { DefaultTheme } from 'vitepress/theme'
3
4
  import { onMounted, ref, watch } from 'vue'
4
5
  import { useAside } from '../composables/aside'
5
- import { useData } from '../composables/data'
6
6
 
7
- const { page } = useData()
7
+ const route = useRoute()
8
8
  const props = defineProps<{
9
9
  carbonAds: DefaultTheme.CarbonAdsOptions
10
10
  }>()
@@ -32,7 +32,7 @@ function init() {
32
32
  }
33
33
  }
34
34
 
35
- watch(() => page.value.relativePath, () => {
35
+ watch(() => route.data.relativePath, () => {
36
36
  if (isInitialized && isAsideEnabled.value) {
37
37
  ;(window as any)._carbonads?.refresh()
38
38
  }
@@ -7,7 +7,6 @@ import VPDocAside from './VPDocAside.vue'
7
7
  import VPDocFooter from './VPDocFooter.vue'
8
8
 
9
9
  const { theme } = useData()
10
-
11
10
  const route = useRoute()
12
11
  const { hasSidebar, hasAside, leftAside } = useLayout()
13
12
 
@@ -53,6 +53,8 @@ const showFooter = computed(
53
53
  v-if="control.prev?.link"
54
54
  class="pager-link prev"
55
55
  :href="control.prev.link"
56
+ :target="control.prev.target"
57
+ :rel="control.prev.rel"
56
58
  >
57
59
  <span
58
60
  class="desc"
@@ -66,6 +68,8 @@ const showFooter = computed(
66
68
  v-if="control.next?.link"
67
69
  class="pager-link next"
68
70
  :href="control.next.link"
71
+ :target="control.next.target"
72
+ :rel="control.next.rel"
69
73
  >
70
74
  <span
71
75
  class="desc"
@@ -39,7 +39,7 @@ onMounted(() => {
39
39
 
40
40
  <template>
41
41
  <p class="VPLastUpdated">
42
- {{ theme.lastUpdated?.text || theme.lastUpdatedText || 'Last updated' }}:
42
+ {{ theme.lastUpdated?.text || 'Last updated' }}:
43
43
  <time ref="timeRef" :datetime="isoDatetime">{{ datetime }}</time>
44
44
  </p>
45
45
  </template>
@@ -37,8 +37,8 @@ const grid = computed(() => {
37
37
  <template>
38
38
  <div v-if="features" class="VPFeatures">
39
39
  <div class="container">
40
- <div class="items">
41
- <div
40
+ <ul class="items">
41
+ <li
42
42
  v-for="feature in features"
43
43
  :key="feature.title"
44
44
  class="item"
@@ -53,8 +53,8 @@ const grid = computed(() => {
53
53
  :rel="feature.rel"
54
54
  :target="feature.target"
55
55
  />
56
- </div>
57
- </div>
56
+ </li>
57
+ </ul>
58
58
  </div>
59
59
  </div>
60
60
  </template>
@@ -11,6 +11,7 @@ const { width: vw } = useWindowSize({
11
11
  <div
12
12
  class="vp-doc container"
13
13
  :style="vw ? { '--vp-offset': `calc(50% - ${vw / 2}px)` } : {}"
14
+ data-allow-mismatch="style"
14
15
  >
15
16
  <slot />
16
17
  </div>
@@ -40,7 +40,7 @@ defineOptions({ inheritAttrs: false })
40
40
  html:not(.dark) .VPImage.dark {
41
41
  display: none;
42
42
  }
43
- .dark .VPImage.light {
43
+ html.dark .VPImage.light {
44
44
  display: none;
45
45
  }
46
46
  </style>
@@ -2,14 +2,16 @@
2
2
  import { computed } from 'vue'
3
3
  import { isLinkExternal, normalizeLink } from '../support/utils'
4
4
 
5
- const props = defineProps<{
5
+ const props = withDefaults(defineProps<{
6
6
  tag?: string
7
7
  href?: string
8
8
  noIcon?: boolean
9
9
  external?: boolean
10
10
  target?: string
11
11
  rel?: string
12
- }>()
12
+ }>(), {
13
+ external: undefined,
14
+ })
13
15
 
14
16
  const tag = computed(() => props.tag ?? (props.href ? 'a' : 'span'))
15
17
  const isExternal = computed(() =>
@@ -65,9 +65,10 @@ function scrollToTop() {
65
65
 
66
66
  <template>
67
67
  <div
68
+ ref="main"
68
69
  class="VPLocalNavOutlineDropdown"
69
70
  :style="{ '--vp-vh': vh + 'px' }"
70
- ref="main"
71
+ data-allow-mismatch="style"
71
72
  >
72
73
  <button @click="toggle" :class="{ open }" v-if="headers.length > 0">
73
74
  <span class="menu-text">{{ resolveTitle(theme) }}</span>
@@ -117,8 +117,7 @@ const showDetailedList = useLocalStorage(
117
117
  const disableDetailedView = computed(() => {
118
118
  return (
119
119
  theme.value.search?.provider === 'local' &&
120
- (theme.value.search.options?.disableDetailedView === true ||
121
- theme.value.search.options?.detailedView === false)
120
+ theme.value.search.options?.detailedView === false
122
121
  )
123
122
  })
124
123
 
@@ -730,7 +729,7 @@ function onMouseMove(e: MouseEvent) {
730
729
  }
731
730
  }
732
731
 
733
- @media (min-width: 769px) {
732
+ @media (min-width: 768px) {
734
733
  .search-actions.before {
735
734
  display: none;
736
735
  }
@@ -10,8 +10,8 @@ defineProps<{
10
10
 
11
11
  <template>
12
12
  <div class="VPMenu">
13
- <div v-if="items" class="items">
14
- <template v-for="item in items" :key="JSON.stringify(item)">
13
+ <ul v-if="items" class="items">
14
+ <li v-for="item in items" :key="JSON.stringify(item)">
15
15
  <VPMenuLink v-if="'link' in item" :item />
16
16
  <component
17
17
  v-else-if="'component' in item"
@@ -19,8 +19,8 @@ defineProps<{
19
19
  v-bind="item.props"
20
20
  />
21
21
  <VPMenuGroup v-else :text="item.text" :items="item.items" />
22
- </template>
23
- </div>
22
+ </li>
23
+ </ul>
24
24
 
25
25
  <slot />
26
26
  </div>
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" setup generic="T extends DefaultTheme.NavItemWithLink">
2
+ import { useRoute } from 'vitepress'
2
3
  import type { DefaultTheme } from 'vitepress/theme'
3
4
  import { computed } from 'vue'
4
5
  import { isActive } from '../../shared'
5
- import { useData } from '../composables/data'
6
6
  import VPLink from './VPLink.vue'
7
7
 
8
8
  const props = defineProps<{
@@ -10,21 +10,22 @@ const props = defineProps<{
10
10
  rel?: string
11
11
  }>()
12
12
 
13
- const { page } = useData()
13
+ const route = useRoute()
14
14
 
15
15
  const href = computed(() =>
16
16
  typeof props.item.link === 'function'
17
- ? props.item.link(page.value)
17
+ ? props.item.link(route.data)
18
18
  : props.item.link
19
19
  )
20
20
 
21
- const isActiveLink = computed(() =>
22
- isActive(
23
- page.value.relativePath,
21
+ const isActiveLink = computed(() => {
22
+ return isActive(
23
+ route.data.relativePath,
24
+ route.hash,
24
25
  props.item.activeMatch || href.value,
25
26
  !!props.item.activeMatch
26
27
  )
27
- )
28
+ })
28
29
 
29
30
  defineOptions({ inheritAttrs: false })
30
31
  </script>
@@ -8,7 +8,9 @@ import VPSocialLinks from './VPSocialLinks.vue'
8
8
  import VPSwitchAppearance from './VPSwitchAppearance.vue'
9
9
 
10
10
  const { site, theme } = useData()
11
- const { localeLinks, currentLang } = useLangs({ correspondingLink: true })
11
+ const { localeLinks, currentLang } = useLangs({
12
+ linkToCorrespondingPage: true
13
+ })
12
14
 
13
15
  const hasExtraContent = computed(
14
16
  () =>
@@ -24,13 +26,13 @@ const hasExtraContent = computed(
24
26
  class="VPNavBarExtra"
25
27
  label="extra navigation"
26
28
  >
27
- <div
29
+ <ul
28
30
  v-if="localeLinks.length && currentLang.label"
29
31
  class="group translations"
30
32
  >
31
- <p class="trans-title">{{ currentLang.label }}</p>
33
+ <li class="trans-title">{{ currentLang.label }}</li>
32
34
 
33
- <template v-for="locale in localeLinks" :key="locale.link">
35
+ <li v-for="locale in localeLinks" :key="locale.link">
34
36
  <VPMenuLink
35
37
  :item="locale"
36
38
  :external="false"
@@ -38,9 +40,10 @@ const hasExtraContent = computed(
38
40
  :hreflang="locale.lang"
39
41
  rel="alternate"
40
42
  :dir="locale.dir"
43
+ data-allow-mismatch="attribute"
41
44
  />
42
- </template>
43
- </div>
45
+ </li>
46
+ </ul>
44
47
 
45
48
  <div
46
49
  v-if="