vitepress 2.0.0-alpha.11 → 2.0.0-alpha.13

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 (31) hide show
  1. package/dist/client/app/composables/copyCode.js +5 -3
  2. package/dist/client/app/data.js +1 -9
  3. package/dist/client/app/router.js +39 -17
  4. package/dist/client/shared.js +4 -0
  5. package/dist/client/theme-default/components/VPAlgoliaSearchBox.vue +1 -1
  6. package/dist/client/theme-default/components/VPBadge.vue +1 -0
  7. package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +22 -10
  8. package/dist/client/theme-default/components/VPDocOutlineItem.vue +1 -7
  9. package/dist/client/theme-default/components/VPLocalNav.vue +5 -10
  10. package/dist/client/theme-default/components/VPLocalNavOutlineDropdown.vue +0 -10
  11. package/dist/client/theme-default/components/VPMenuLink.vue +14 -3
  12. package/dist/client/theme-default/components/VPNavBar.vue +8 -2
  13. package/dist/client/theme-default/components/VPNavBarExtra.vue +1 -1
  14. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +1 -1
  15. package/dist/client/theme-default/components/VPNavBarMenuLink.vue +10 -3
  16. package/dist/client/theme-default/components/VPNavBarTranslations.vue +1 -1
  17. package/dist/client/theme-default/components/VPNavScreenMenuGroupLink.vue +12 -3
  18. package/dist/client/theme-default/components/VPNavScreenMenuLink.vue +12 -3
  19. package/dist/client/theme-default/components/VPNavScreenTranslations.vue +8 -1
  20. package/dist/client/theme-default/components/VPSidebar.vue +3 -3
  21. package/dist/client/theme-default/components/VPSkipLink.vue +2 -23
  22. package/dist/client/theme-default/composables/langs.js +3 -1
  23. package/dist/client/theme-default/composables/outline.js +1 -1
  24. package/dist/client/theme-default/styles/components/vp-doc.css +1 -1
  25. package/dist/client/theme-default/styles/icons.css +2 -2
  26. package/dist/node/{chunk-CwUP9ZhX.js → chunk-ChGxanGi.js} +7519 -4597
  27. package/dist/node/cli.js +55 -47
  28. package/dist/node/index.d.ts +66 -33
  29. package/dist/node/index.js +41 -24
  30. package/package.json +52 -52
  31. package/types/default-theme.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  import { inBrowser } from 'vitepress';
2
- const shellRE = /language-(shellscript|shell|bash|sh|zsh)/;
2
+ import { isShell } from '../../shared';
3
3
  const ignoredNodes = ['.vp-copy-ignore', '.diff.remove'].join(', ');
4
4
  export function useCopyCode() {
5
5
  if (inBrowser) {
@@ -12,7 +12,6 @@ export function useCopyCode() {
12
12
  if (!parent || !sibling) {
13
13
  return;
14
14
  }
15
- const isShell = shellRE.test(parent.className);
16
15
  // Clone the node and remove the ignored nodes
17
16
  const clone = sibling.cloneNode(true);
18
17
  clone.querySelectorAll(ignoredNodes).forEach((node) => node.remove());
@@ -20,7 +19,10 @@ export function useCopyCode() {
20
19
  // doesn't affect the newlines already in the code because they are rendered as `\n<span class="line"></span>`
21
20
  clone.innerHTML = clone.innerHTML.replace(/\n+/g, '\n');
22
21
  let text = clone.textContent || '';
23
- if (isShell) {
22
+ // NOTE: Any changes to this the code here may also need to update
23
+ // `transformerDisableShellSymbolSelect` in `src/node/markdown/plugins/highlight.ts`
24
+ const lang = /language-(\w+)/.exec(parent.className)?.[1] || '';
25
+ if (isShell(lang)) {
24
26
  text = text.replace(/^ *(\$|>) /gm, '').trim();
25
27
  }
26
28
  copyToClipboard(text).then(() => {
@@ -4,15 +4,7 @@ import { computed, inject, readonly, ref, shallowRef, watch } from 'vue';
4
4
  import { APPEARANCE_KEY, createTitle, inBrowser, resolveSiteDataByRoute } from '../shared';
5
5
  export const dataSymbol = Symbol();
6
6
  // site data is a singleton
7
- export const siteDataRef = shallowRef((import.meta.env.PROD ? siteData : readonly(siteData)));
8
- // hmr
9
- if (import.meta.hot) {
10
- import.meta.hot.accept('@siteData', (m) => {
11
- if (m) {
12
- siteDataRef.value = m.default;
13
- }
14
- });
15
- }
7
+ export const siteDataRef = shallowRef(readonly(siteData));
16
8
  // per-app data
17
9
  export function initData(route) {
18
10
  const site = computed(() => resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath));
@@ -4,7 +4,7 @@ import { siteDataRef } from './data';
4
4
  import { getScrollOffset, inBrowser, withBase } from './utils';
5
5
  export const RouterSymbol = Symbol();
6
6
  // we are just using URL to parse the pathname and hash - the base doesn't
7
- // matter and is only passed to support same-host hrefs.
7
+ // matter and is only passed to support same-host hrefs
8
8
  const fakeHost = 'http://a.com';
9
9
  const getDefaultRoute = () => ({
10
10
  path: '/',
@@ -177,21 +177,43 @@ export function scrollTo(hash, smooth = false, scrollPosition = 0) {
177
177
  catch (e) {
178
178
  console.warn(e);
179
179
  }
180
- if (target) {
181
- const targetPadding = parseInt(window.getComputedStyle(target).paddingTop, 10);
182
- const targetTop = window.scrollY +
183
- target.getBoundingClientRect().top -
184
- getScrollOffset() +
185
- targetPadding;
186
- function scrollToTarget() {
187
- // only smooth scroll if distance is smaller than screen height.
188
- if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight)
189
- window.scrollTo(0, targetTop);
190
- else
191
- window.scrollTo({ left: 0, top: targetTop, behavior: 'smooth' });
192
- }
193
- requestAnimationFrame(scrollToTarget);
194
- }
180
+ if (!target)
181
+ return;
182
+ const targetTop = window.scrollY +
183
+ target.getBoundingClientRect().top -
184
+ getScrollOffset() +
185
+ Number.parseInt(window.getComputedStyle(target).paddingTop, 10) || 0;
186
+ const behavior = window.matchMedia('(prefers-reduced-motion)').matches
187
+ ? 'instant'
188
+ : // only smooth scroll if distance is smaller than screen height
189
+ smooth && Math.abs(targetTop - window.scrollY) <= window.innerHeight
190
+ ? 'smooth'
191
+ : 'auto';
192
+ const scrollToTarget = () => {
193
+ window.scrollTo({ left: 0, top: targetTop, behavior });
194
+ // focus the target element for better accessibility
195
+ target.focus({ preventScroll: true });
196
+ // return if focus worked
197
+ if (document.activeElement === target)
198
+ return;
199
+ // element has tabindex already, likely not focusable
200
+ // because of some other reason, bail out
201
+ if (target.hasAttribute('tabindex'))
202
+ return;
203
+ const restoreTabindex = () => {
204
+ target.removeAttribute('tabindex');
205
+ target.removeEventListener('blur', restoreTabindex);
206
+ };
207
+ // temporarily make the target element focusable
208
+ target.setAttribute('tabindex', '-1');
209
+ target.addEventListener('blur', restoreTabindex);
210
+ // try to focus again
211
+ target.focus({ preventScroll: true });
212
+ // remove tabindex and event listener if focus still not worked
213
+ if (document.activeElement !== target)
214
+ restoreTabindex();
215
+ };
216
+ requestAnimationFrame(scrollToTarget);
195
217
  }
196
218
  function handleHMR(route) {
197
219
  // update route.data on HMR updates of active page
@@ -213,7 +235,7 @@ function shouldHotReload(payload) {
213
235
  function normalizeHref(href) {
214
236
  const url = new URL(href, fakeHost);
215
237
  url.pathname = url.pathname.replace(/(^|\/)index(\.html)?$/, '$1');
216
- // ensure correct deep link so page refresh lands on correct files.
238
+ // ensure correct deep link so page refresh lands on correct files
217
239
  if (siteDataRef.value.cleanUrls) {
218
240
  url.pathname = url.pathname.replace(/\.html$/, '');
219
241
  }
@@ -237,3 +237,7 @@ stackView.unpack = function (obj) {
237
237
  export function isObject(value) {
238
238
  return Object.prototype.toString.call(value) === '[object Object]';
239
239
  }
240
+ const shellLangs = ['shellscript', 'shell', 'bash', 'sh', 'zsh'];
241
+ export function isShell(lang) {
242
+ return shellLangs.includes(lang);
243
+ }
@@ -78,7 +78,7 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
78
78
  }
79
79
  })
80
80
 
81
- docsearch(options)
81
+ docsearch(options as any)
82
82
  }
83
83
 
84
84
  function getRelativePath(url: string) {
@@ -24,6 +24,7 @@ withDefaults(defineProps<Props>(), {
24
24
  line-height: 22px;
25
25
  font-size: 12px;
26
26
  font-weight: 500;
27
+ white-space: nowrap;
27
28
  transform: translateY(-2px);
28
29
  }
29
30
 
@@ -1,26 +1,38 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, watchEffect, onMounted } from 'vue'
2
+ import { useNavigatorLanguage } from '@vueuse/core'
3
+ import { computed, onMounted, shallowRef, useTemplateRef, watchEffect } from 'vue'
3
4
  import { useData } from '../composables/data'
4
5
 
5
- const { theme, page, lang } = useData()
6
+ const { theme, page, lang: pageLang } = useData()
7
+ const { language: browserLang } = useNavigatorLanguage()
6
8
 
7
- const date = computed(
8
- () => new Date(page.value.lastUpdated!)
9
- )
9
+ const timeRef = useTemplateRef('timeRef')
10
+
11
+ const date = computed(() => new Date(page.value.lastUpdated!))
10
12
  const isoDatetime = computed(() => date.value.toISOString())
11
- const datetime = ref('')
13
+ const datetime = shallowRef('')
12
14
 
13
15
  // set time on mounted hook to avoid hydration mismatch due to
14
16
  // potential differences in timezones of the server and clients
15
17
  onMounted(() => {
16
18
  watchEffect(() => {
19
+ const lang = theme.value.lastUpdated?.formatOptions?.forceLocale
20
+ ? pageLang.value
21
+ : browserLang.value
22
+
17
23
  datetime.value = new Intl.DateTimeFormat(
18
- theme.value.lastUpdated?.formatOptions?.forceLocale ? lang.value : undefined,
24
+ lang,
19
25
  theme.value.lastUpdated?.formatOptions ?? {
20
- dateStyle: 'short',
21
- timeStyle: 'short'
26
+ dateStyle: 'medium',
27
+ timeStyle: 'medium'
22
28
  }
23
29
  ).format(date.value)
30
+
31
+ if (lang && pageLang.value !== lang) {
32
+ timeRef.value?.setAttribute('lang', lang)
33
+ } else {
34
+ timeRef.value?.removeAttribute('lang')
35
+ }
24
36
  })
25
37
  })
26
38
  </script>
@@ -28,7 +40,7 @@ onMounted(() => {
28
40
  <template>
29
41
  <p class="VPLastUpdated">
30
42
  {{ theme.lastUpdated?.text || theme.lastUpdatedText || 'Last updated' }}:
31
- <time :datetime="isoDatetime">{{ datetime }}</time>
43
+ <time ref="timeRef" :datetime="isoDatetime">{{ datetime }}</time>
32
44
  </p>
33
45
  </template>
34
46
 
@@ -5,18 +5,12 @@ defineProps<{
5
5
  headers: DefaultTheme.OutlineItem[]
6
6
  root?: boolean
7
7
  }>()
8
-
9
- function onClick({ target: el }: Event) {
10
- const id = (el as HTMLAnchorElement).href!.split('#')[1]
11
- const heading = document.getElementById(decodeURIComponent(id))
12
- heading?.focus({ preventScroll: true })
13
- }
14
8
  </script>
15
9
 
16
10
  <template>
17
11
  <ul class="VPDocOutlineItem" :class="root ? 'root' : 'nested'">
18
12
  <li v-for="{ children, link, title } in headers">
19
- <a class="outline-link" :href="link" @click="onClick" :title>
13
+ <a class="outline-link" :href="link" :title>
20
14
  {{ title }}
21
15
  </a>
22
16
  <template v-if="children?.length">
@@ -32,7 +32,7 @@ const classes = computed(() => {
32
32
  VPLocalNav: true,
33
33
  'has-sidebar': hasSidebar.value,
34
34
  empty: !hasLocalNav.value,
35
- fixed: !hasLocalNav.value && !hasSidebar.value,
35
+ fixed: !hasLocalNav.value && !hasSidebar.value
36
36
  }
37
37
  })
38
38
  </script>
@@ -113,7 +113,6 @@ const classes = computed(() => {
113
113
  .menu {
114
114
  display: flex;
115
115
  align-items: center;
116
- padding: 12px 24px 11px;
117
116
  line-height: 24px;
118
117
  font-size: 12px;
119
118
  font-weight: 500;
@@ -126,12 +125,6 @@ const classes = computed(() => {
126
125
  transition: color 0.25s;
127
126
  }
128
127
 
129
- @media (min-width: 768px) {
130
- .menu {
131
- padding: 0 32px;
132
- }
133
- }
134
-
135
128
  @media (min-width: 960px) {
136
129
  .menu {
137
130
  display: none;
@@ -143,12 +136,14 @@ const classes = computed(() => {
143
136
  font-size: 14px;
144
137
  }
145
138
 
146
- .VPOutlineDropdown {
139
+ .menu,
140
+ :deep(.VPLocalNavOutlineDropdown > button) {
147
141
  padding: 12px 24px 11px;
148
142
  }
149
143
 
150
144
  @media (min-width: 768px) {
151
- .VPOutlineDropdown {
145
+ .menu,
146
+ :deep(.VPLocalNavOutlineDropdown > button) {
152
147
  padding: 12px 32px 11px;
153
148
  }
154
149
  }
@@ -92,16 +92,6 @@ function scrollToTop() {
92
92
  </template>
93
93
 
94
94
  <style scoped>
95
- .VPLocalNavOutlineDropdown {
96
- padding: 12px 20px 11px;
97
- }
98
-
99
- @media (min-width: 960px) {
100
- .VPLocalNavOutlineDropdown {
101
- padding: 12px 36px 11px;
102
- }
103
- }
104
-
105
95
  .VPLocalNavOutlineDropdown button {
106
96
  display: block;
107
97
  font-size: 12px;
@@ -1,27 +1,37 @@
1
1
  <script lang="ts" setup generic="T extends DefaultTheme.NavItemWithLink">
2
2
  import type { DefaultTheme } from 'vitepress/theme'
3
+ import { computed } from 'vue'
3
4
  import { useData } from '../composables/data'
4
5
  import { isActive } from '../../shared'
5
6
  import VPLink from './VPLink.vue'
6
7
 
7
- defineProps<{
8
+ const props = defineProps<{
8
9
  item: T
9
10
  }>()
10
11
 
11
12
  const { page } = useData()
13
+
14
+ const href = computed(() =>
15
+ typeof props.item.link === 'function'
16
+ ? props.item.link(page.value)
17
+ : props.item.link
18
+ )
19
+
20
+ defineOptions({ inheritAttrs: false })
12
21
  </script>
13
22
 
14
23
  <template>
15
24
  <div class="VPMenuLink">
16
25
  <VPLink
26
+ v-bind="$attrs"
17
27
  :class="{
18
28
  active: isActive(
19
29
  page.relativePath,
20
- item.activeMatch || item.link,
30
+ item.activeMatch || href,
21
31
  !!item.activeMatch
22
32
  )
23
33
  }"
24
- :href="item.link"
34
+ :href
25
35
  :target="item.target"
26
36
  :rel="item.rel"
27
37
  :no-icon="item.noIcon"
@@ -46,6 +56,7 @@ const { page } = useData()
46
56
  font-size: 14px;
47
57
  font-weight: 500;
48
58
  color: var(--vp-c-text-1);
59
+ text-align: left;
49
60
  white-space: nowrap;
50
61
  transition:
51
62
  background-color 0.25s,
@@ -170,16 +170,22 @@ watchPostEffect(() => {
170
170
  .VPNavBar.has-sidebar .content {
171
171
  position: relative;
172
172
  z-index: 1;
173
- padding-right: 32px;
174
173
  padding-left: var(--vp-sidebar-width);
175
174
  }
175
+
176
+ .VPNavBar.has-sidebar .content-body {
177
+ padding-right: 32px;
178
+ }
176
179
  }
177
180
 
178
181
  @media (min-width: 1440px) {
179
182
  .VPNavBar.has-sidebar .content {
180
- padding-right: calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);
181
183
  padding-left: calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width));
182
184
  }
185
+
186
+ .VPNavBar.has-sidebar .content-body {
187
+ padding-right: calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);
188
+ }
183
189
  }
184
190
 
185
191
  .content-body {
@@ -31,7 +31,7 @@ const hasExtraContent = computed(
31
31
  <p class="trans-title">{{ currentLang.label }}</p>
32
32
 
33
33
  <template v-for="locale in localeLinks" :key="locale.link">
34
- <VPMenuLink :item="locale" />
34
+ <VPMenuLink :item="locale" :lang="locale.lang" :dir="locale.dir" />
35
35
  </template>
36
36
  </div>
37
37
 
@@ -17,7 +17,7 @@ const isChildActive = (navItem: DefaultTheme.NavItem) => {
17
17
  if ('link' in navItem) {
18
18
  return isActive(
19
19
  page.value.relativePath,
20
- navItem.link,
20
+ typeof navItem.link === "function" ? navItem.link(page.value) : navItem.link,
21
21
  !!props.item.activeMatch
22
22
  )
23
23
  }
@@ -1,14 +1,21 @@
1
1
  <script lang="ts" setup>
2
2
  import type { DefaultTheme } from 'vitepress/theme'
3
+ import { computed } from 'vue'
3
4
  import { useData } from '../composables/data'
4
5
  import { isActive } from '../../shared'
5
6
  import VPLink from './VPLink.vue'
6
7
 
7
- defineProps<{
8
+ const props = defineProps<{
8
9
  item: DefaultTheme.NavItemWithLink
9
10
  }>()
10
11
 
11
12
  const { page } = useData()
13
+
14
+ const href = computed(() =>
15
+ typeof props.item.link === 'function'
16
+ ? props.item.link(page.value)
17
+ : props.item.link
18
+ )
12
19
  </script>
13
20
 
14
21
  <template>
@@ -17,11 +24,11 @@ const { page } = useData()
17
24
  VPNavBarMenuLink: true,
18
25
  active: isActive(
19
26
  page.relativePath,
20
- item.activeMatch || item.link,
27
+ item.activeMatch || href,
21
28
  !!item.activeMatch
22
29
  )
23
30
  }"
24
- :href="item.link"
31
+ :href
25
32
  :target="item.target"
26
33
  :rel="item.rel"
27
34
  :no-icon="item.noIcon"
@@ -19,7 +19,7 @@ const { localeLinks, currentLang } = useLangs({ correspondingLink: true })
19
19
  <p class="title">{{ currentLang.label }}</p>
20
20
 
21
21
  <template v-for="locale in localeLinks" :key="locale.link">
22
- <VPMenuLink :item="locale" />
22
+ <VPMenuLink :item="locale" :lang="locale.lang" :dir="locale.dir" />
23
23
  </template>
24
24
  </div>
25
25
  </VPFlyout>
@@ -1,20 +1,29 @@
1
1
  <script lang="ts" setup>
2
2
  import type { DefaultTheme } from 'vitepress/theme'
3
- import { inject } from 'vue'
3
+ import { computed, inject } from 'vue'
4
+ import { useData } from '../composables/data'
4
5
  import { navInjectionKey } from '../composables/nav'
5
6
  import VPLink from './VPLink.vue'
6
7
 
7
- defineProps<{
8
+ const props = defineProps<{
8
9
  item: DefaultTheme.NavItemWithLink
9
10
  }>()
10
11
 
12
+ const { page } = useData()
13
+
14
+ const href = computed(() =>
15
+ typeof props.item.link === 'function'
16
+ ? props.item.link(page.value)
17
+ : props.item.link
18
+ )
19
+
11
20
  const { closeScreen } = inject(navInjectionKey)!
12
21
  </script>
13
22
 
14
23
  <template>
15
24
  <VPLink
16
25
  class="VPNavScreenMenuGroupLink"
17
- :href="item.link"
26
+ :href
18
27
  :target="item.target"
19
28
  :rel="item.rel"
20
29
  :no-icon="item.noIcon"
@@ -1,20 +1,29 @@
1
1
  <script lang="ts" setup>
2
2
  import type { DefaultTheme } from 'vitepress/theme'
3
- import { inject } from 'vue'
3
+ import { computed, inject } from 'vue'
4
+ import { useData } from '../composables/data'
4
5
  import { navInjectionKey } from '../composables/nav'
5
6
  import VPLink from './VPLink.vue'
6
7
 
7
- defineProps<{
8
+ const props = defineProps<{
8
9
  item: DefaultTheme.NavItemWithLink
9
10
  }>()
10
11
 
12
+ const { page } = useData()
13
+
14
+ const href = computed(() =>
15
+ typeof props.item.link === 'function'
16
+ ? props.item.link(page.value)
17
+ : props.item.link
18
+ )
19
+
11
20
  const { closeScreen } = inject(navInjectionKey)!
12
21
  </script>
13
22
 
14
23
  <template>
15
24
  <VPLink
16
25
  class="VPNavScreenMenuLink"
17
- :href="item.link"
26
+ :href
18
27
  :target="item.target"
19
28
  :rel="item.rel"
20
29
  :no-icon="item.noIcon"
@@ -25,7 +25,14 @@ function toggle() {
25
25
 
26
26
  <ul class="list">
27
27
  <li v-for="locale in localeLinks" :key="locale.link" class="item">
28
- <VPLink class="link" :href="locale.link">{{ locale.text }}</VPLink>
28
+ <VPLink
29
+ class="link"
30
+ :href="locale.link"
31
+ :lang="locale.lang"
32
+ :dir="locale.dir"
33
+ >
34
+ {{ locale.text }}
35
+ </VPLink>
29
36
  </li>
30
37
  </ul>
31
38
  </div>
@@ -111,15 +111,15 @@ watch(
111
111
 
112
112
  @media (min-width: 1440px) {
113
113
  .VPSidebar {
114
- padding-left: max(32px, calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));
115
- width: calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px);
114
+ padding-left: max(32px, calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2));
115
+ width: calc((100vw - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px);
116
116
  }
117
117
  }
118
118
 
119
119
  @media (min-width: 960px) {
120
120
  .curtain {
121
121
  position: sticky;
122
- top: -64px;
122
+ top: calc(var(--vp-nav-height) * -1);
123
123
  left: 0;
124
124
  z-index: 1;
125
125
  margin-top: calc(var(--vp-nav-height) * -1);
@@ -8,39 +8,18 @@ const route = useRoute()
8
8
  const backToTop = ref()
9
9
 
10
10
  watch(() => route.path, () => backToTop.value.focus())
11
-
12
- function focusOnTargetAnchor({ target }: Event) {
13
- const el = document.getElementById(
14
- decodeURIComponent((target as HTMLAnchorElement).hash).slice(1)
15
- )
16
-
17
- if (el) {
18
- const removeTabIndex = () => {
19
- el.removeAttribute('tabindex')
20
- el.removeEventListener('blur', removeTabIndex)
21
- }
22
-
23
- el.setAttribute('tabindex', '-1')
24
- el.addEventListener('blur', removeTabIndex)
25
- el.focus()
26
- window.scrollTo(0, 0)
27
- }
28
- }
29
11
  </script>
30
12
 
31
13
  <template>
32
14
  <span ref="backToTop" tabindex="-1" />
33
- <a
34
- href="#VPContent"
35
- class="VPSkipLink visually-hidden"
36
- @click="focusOnTargetAnchor"
37
- >
15
+ <a href="#VPContent" class="VPSkipLink visually-hidden">
38
16
  {{ theme.skipToContentLabel || 'Skip to content' }}
39
17
  </a>
40
18
  </template>
41
19
 
42
20
  <style scoped>
43
21
  .VPSkipLink {
22
+ position: fixed;
44
23
  top: 8px;
45
24
  left: 8px;
46
25
  padding: 8px 16px;
@@ -12,7 +12,9 @@ export function useLangs({ correspondingLink = false } = {}) {
12
12
  ? []
13
13
  : {
14
14
  text: value.label,
15
- link: normalizeLink(value.link || (key === 'root' ? '/' : `/${key}/`), theme.value.i18nRouting !== false && correspondingLink, page.value.relativePath.slice(currentLang.value.link.length - 1), !site.value.cleanUrls) + hash.value
15
+ link: normalizeLink(value.link || (key === 'root' ? '/' : `/${key}/`), theme.value.i18nRouting !== false && correspondingLink, page.value.relativePath.slice(currentLang.value.link.length - 1), !site.value.cleanUrls) + hash.value,
16
+ lang: value.lang,
17
+ dir: value.dir
16
18
  }));
17
19
  return { localeLinks, currentLang };
18
20
  }
@@ -14,7 +14,7 @@ export function resolveTitle(theme) {
14
14
  }
15
15
  export function getHeaders(range) {
16
16
  const headers = [
17
- ...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)')
17
+ ...document.querySelectorAll('.VPDoc h1, .VPDoc h2, .VPDoc h3, .VPDoc h4, .VPDoc h5, .VPDoc h6')
18
18
  ]
19
19
  .filter((el) => el.id && el.hasChildNodes())
20
20
  .map((el) => {
@@ -226,7 +226,7 @@
226
226
  }
227
227
 
228
228
  .vp-doc .custom-block div[class*='language-'] {
229
- margin: 8px 0;
229
+ margin: 8px 0 !important;
230
230
  border-radius: 8px;
231
231
  }
232
232
 
@@ -88,6 +88,6 @@
88
88
  :root {
89
89
  /* clipboard */
90
90
  --vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/g%3E%3C/svg%3E");
91
- /* clipboard-copy */
92
- --vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2M16 4h2a2 2 0 0 1 2 2v4m1 4H11'/%3E%3Cpath d='m15 10l-4 4l4 4'/%3E%3C/g%3E%3C/svg%3E");
91
+ /* clipboard-check */
92
+ --vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14l2 2l4-4'/%3E%3C/g%3E%3C/svg%3E");
93
93
  }