vitepress 1.0.0-beta.3 → 1.0.0-beta.4

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