vitepress 1.2.2 → 1.3.0

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 (29) hide show
  1. package/dist/client/app/data.js +1 -1
  2. package/dist/client/app/router.js +41 -40
  3. package/dist/client/theme-default/components/VPDocFooter.vue +29 -13
  4. package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +2 -2
  5. package/dist/client/theme-default/components/VPMenu.vue +7 -2
  6. package/dist/client/theme-default/components/VPNavBar.vue +10 -3
  7. package/dist/client/theme-default/components/VPNavBarAppearance.vue +8 -1
  8. package/dist/client/theme-default/components/VPNavBarExtra.vue +17 -3
  9. package/dist/client/theme-default/components/VPNavBarMenu.vue +14 -3
  10. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +7 -7
  11. package/dist/client/theme-default/components/VPNavScreen.vue +2 -2
  12. package/dist/client/theme-default/components/VPNavScreenAppearance.vue +8 -1
  13. package/dist/client/theme-default/components/VPNavScreenMenu.vue +7 -4
  14. package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +9 -8
  15. package/dist/client/theme-default/components/VPSidebar.vue +18 -19
  16. package/dist/client/theme-default/components/VPSidebarGroup.vue +56 -0
  17. package/dist/client/theme-default/components/VPSidebarItem.vue +3 -3
  18. package/dist/client/theme-default/components/VPSwitchAppearance.vue +5 -3
  19. package/dist/client/theme-default/styles/base.css +1 -2
  20. package/dist/client/theme-default/styles/components/vp-doc.css +10 -2
  21. package/dist/client/theme-default/without-fonts.js +1 -0
  22. package/dist/node/cli.js +20 -14
  23. package/dist/node/index.d.ts +7 -6
  24. package/dist/node/index.js +2 -2
  25. package/dist/node/{serve-BwR5EPUJ.js → serve-BhLFz9dF.js} +713 -395
  26. package/package.json +41 -44
  27. package/theme.d.ts +1 -0
  28. package/types/default-theme.d.ts +9 -4
  29. package/types/shared.d.ts +1 -0
@@ -22,7 +22,7 @@ export function initData(route) {
22
22
  : appearance
23
23
  ? useDark({
24
24
  storageKey: APPEARANCE_KEY,
25
- initialValue: () => typeof appearance === 'string' ? appearance : 'auto',
25
+ initialValue: () => (appearance === 'dark' ? 'dark' : 'auto'),
26
26
  ...(typeof appearance === 'object' ? appearance : {})
27
27
  })
28
28
  : ref(false);
@@ -117,52 +117,53 @@ export function createRouter(loadPageModule, fallbackComponent) {
117
117
  history.replaceState({}, '');
118
118
  }
119
119
  window.addEventListener('click', (e) => {
120
- // temporary fix for docsearch action buttons
121
- const button = e.target.closest('button');
122
- if (button)
120
+ if (e.defaultPrevented ||
121
+ !(e.target instanceof Element) ||
122
+ e.target.closest('button') || // temporary fix for docsearch action buttons
123
+ e.button !== 0 ||
124
+ e.ctrlKey ||
125
+ e.shiftKey ||
126
+ e.altKey ||
127
+ e.metaKey)
123
128
  return;
124
129
  const link = e.target.closest('a');
125
- if (link &&
126
- !link.closest('.vp-raw') &&
127
- (link instanceof SVGElement || !link.download)) {
128
- const { target } = link;
129
- const { href, origin, pathname, hash, search } = new URL(link.href instanceof SVGAnimatedString
130
- ? link.href.animVal
131
- : link.href, link.baseURI);
132
- const currentUrl = new URL(location.href); // copy to keep old data
133
- // only intercept inbound html links
134
- if (!e.ctrlKey &&
135
- !e.shiftKey &&
136
- !e.altKey &&
137
- !e.metaKey &&
138
- !target &&
139
- origin === currentUrl.origin &&
140
- treatAsHtml(pathname)) {
141
- e.preventDefault();
142
- if (pathname === currentUrl.pathname &&
143
- search === currentUrl.search) {
144
- // scroll between hash anchors in the same page
145
- // avoid duplicate history entries when the hash is same
146
- if (hash !== currentUrl.hash) {
147
- history.pushState({}, '', href);
148
- // still emit the event so we can listen to it in themes
149
- window.dispatchEvent(new HashChangeEvent('hashchange', {
150
- oldURL: currentUrl.href,
151
- newURL: href
152
- }));
153
- }
154
- if (hash) {
155
- // use smooth scroll when clicking on header anchor links
156
- scrollTo(link, hash, link.classList.contains('header-anchor'));
157
- }
158
- else {
159
- window.scrollTo(0, 0);
160
- }
130
+ if (!link ||
131
+ link.closest('.vp-raw') ||
132
+ link.hasAttribute('download') ||
133
+ link.hasAttribute('target'))
134
+ return;
135
+ const linkHref = link.getAttribute('href') ??
136
+ (link instanceof SVGAElement ? link.getAttribute('xlink:href') : null);
137
+ if (linkHref == null)
138
+ return;
139
+ const { href, origin, pathname, hash, search } = new URL(linkHref, link.baseURI);
140
+ const currentUrl = new URL(location.href); // copy to keep old data
141
+ // only intercept inbound html links
142
+ if (origin === currentUrl.origin && treatAsHtml(pathname)) {
143
+ e.preventDefault();
144
+ if (pathname === currentUrl.pathname &&
145
+ search === currentUrl.search) {
146
+ // scroll between hash anchors in the same page
147
+ // avoid duplicate history entries when the hash is same
148
+ if (hash !== currentUrl.hash) {
149
+ history.pushState({}, '', href);
150
+ // still emit the event so we can listen to it in themes
151
+ window.dispatchEvent(new HashChangeEvent('hashchange', {
152
+ oldURL: currentUrl.href,
153
+ newURL: href
154
+ }));
155
+ }
156
+ if (hash) {
157
+ // use smooth scroll when clicking on header anchor links
158
+ scrollTo(link, hash, link.classList.contains('header-anchor'));
161
159
  }
162
160
  else {
163
- go(href);
161
+ window.scrollTo(0, 0);
164
162
  }
165
163
  }
164
+ else {
165
+ go(href);
166
+ }
166
167
  }
167
168
  }, { capture: true });
168
169
  window.addEventListener('popstate', async (e) => {
@@ -11,15 +11,17 @@ const { theme, page, frontmatter } = useData()
11
11
  const editLink = useEditLink()
12
12
  const control = usePrevNext()
13
13
 
14
- const hasEditLink = computed(() => {
15
- return theme.value.editLink && frontmatter.value.editLink !== false
16
- })
17
- const hasLastUpdated = computed(() => {
18
- return page.value.lastUpdated && frontmatter.value.lastUpdated !== false
19
- })
20
- const showFooter = computed(() => {
21
- return hasEditLink.value || hasLastUpdated.value || control.value.prev || control.value.next
22
- })
14
+ const hasEditLink = computed(
15
+ () => theme.value.editLink && frontmatter.value.editLink !== false
16
+ )
17
+ const hasLastUpdated = computed(() => page.value.lastUpdated)
18
+ const showFooter = computed(
19
+ () =>
20
+ hasEditLink.value ||
21
+ hasLastUpdated.value ||
22
+ control.value.prev ||
23
+ control.value.next
24
+ )
23
25
  </script>
24
26
 
25
27
  <template>
@@ -47,14 +49,28 @@ const showFooter = computed(() => {
47
49
  <span class="visually-hidden" id="doc-footer-aria-label">Pager</span>
48
50
 
49
51
  <div class="pager">
50
- <VPLink v-if="control.prev?.link" class="pager-link prev" :href="control.prev.link">
51
- <span class="desc" v-html="theme.docFooter?.prev || 'Previous page'"></span>
52
+ <VPLink
53
+ v-if="control.prev?.link"
54
+ class="pager-link prev"
55
+ :href="control.prev.link"
56
+ >
57
+ <span
58
+ class="desc"
59
+ v-html="theme.docFooter?.prev || 'Previous page'"
60
+ ></span>
52
61
  <span class="title" v-html="control.prev.text"></span>
53
62
  </VPLink>
54
63
  </div>
55
64
  <div class="pager">
56
- <VPLink v-if="control.next?.link" class="pager-link next" :href="control.next.link">
57
- <span class="desc" v-html="theme.docFooter?.next || 'Next page'"></span>
65
+ <VPLink
66
+ v-if="control.next?.link"
67
+ class="pager-link next"
68
+ :href="control.next.link"
69
+ >
70
+ <span
71
+ class="desc"
72
+ v-html="theme.docFooter?.next || 'Next page'"
73
+ ></span>
58
74
  <span class="title" v-html="control.next.text"></span>
59
75
  </VPLink>
60
76
  </div>
@@ -2,10 +2,10 @@
2
2
  import { ref, computed, watchEffect, onMounted } from 'vue'
3
3
  import { useData } from '../composables/data'
4
4
 
5
- const { theme, page, frontmatter, lang } = useData()
5
+ const { theme, page, lang } = useData()
6
6
 
7
7
  const date = computed(
8
- () => new Date(frontmatter.value.lastUpdated ?? page.value.lastUpdated)
8
+ () => new Date(page.value.lastUpdated!)
9
9
  )
10
10
  const isoDatetime = computed(() => date.value.toISOString())
11
11
  const datetime = ref('')
@@ -10,8 +10,13 @@ defineProps<{
10
10
  <template>
11
11
  <div class="VPMenu">
12
12
  <div v-if="items" class="items">
13
- <template v-for="item in items" :key="item.text">
13
+ <template v-for="item in items" :key="JSON.stringify(item)">
14
14
  <VPMenuLink v-if="'link' in item" :item="item" />
15
+ <component
16
+ v-else-if="'component' in item"
17
+ :is="item.component"
18
+ v-bind="item.props"
19
+ />
15
20
  <VPMenuGroup v-else :text="item.text" :items="item.items" />
16
21
  </template>
17
22
  </div>
@@ -63,7 +68,7 @@ defineProps<{
63
68
  font-size: 12px;
64
69
  font-weight: 500;
65
70
  color: var(--vp-c-text-2);
66
- transition: color .5s;
71
+ transition: color 0.5s;
67
72
  }
68
73
 
69
74
  .VPMenu :deep(.action) {
@@ -12,7 +12,7 @@ import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
12
12
  import VPNavBarTitle from './VPNavBarTitle.vue'
13
13
  import VPNavBarTranslations from './VPNavBarTranslations.vue'
14
14
 
15
- defineProps<{
15
+ const props = defineProps<{
16
16
  isScreenOpen: boolean
17
17
  }>()
18
18
 
@@ -31,6 +31,7 @@ watchPostEffect(() => {
31
31
  'has-sidebar': hasSidebar.value,
32
32
  'home': frontmatter.value.layout === 'home',
33
33
  'top': y.value === 0,
34
+ 'screen-open': props.isScreenOpen
34
35
  }
35
36
  })
36
37
  </script>
@@ -74,7 +75,13 @@ watchPostEffect(() => {
74
75
  height: var(--vp-nav-height);
75
76
  pointer-events: none;
76
77
  white-space: nowrap;
77
- transition: background-color 0.5s;
78
+ transition: background-color 0.25s;
79
+ }
80
+
81
+ .VPNavBar.screen-open {
82
+ transition: none;
83
+ background-color: var(--vp-nav-bg-color);
84
+ border-bottom: 1px solid var(--vp-c-divider);
78
85
  }
79
86
 
80
87
  .VPNavBar:not(.home) {
@@ -255,7 +262,7 @@ watchPostEffect(() => {
255
262
  background-color: var(--vp-c-gutter);
256
263
  }
257
264
 
258
- @media (min-width: 960px) {
265
+ @media (min-width: 960px) {
259
266
  .VPNavBar:not(.home.top) .divider-line {
260
267
  background-color: var(--vp-c-gutter);
261
268
  }
@@ -6,7 +6,14 @@ const { site } = useData()
6
6
  </script>
7
7
 
8
8
  <template>
9
- <div v-if="site.appearance && site.appearance !== 'force-dark'" class="VPNavBarAppearance">
9
+ <div
10
+ v-if="
11
+ site.appearance &&
12
+ site.appearance !== 'force-dark' &&
13
+ site.appearance !== 'force-auto'
14
+ "
15
+ class="VPNavBarAppearance"
16
+ >
10
17
  <VPSwitchAppearance />
11
18
  </div>
12
19
  </template>
@@ -19,8 +19,15 @@ const hasExtraContent = computed(
19
19
  </script>
20
20
 
21
21
  <template>
22
- <VPFlyout v-if="hasExtraContent" class="VPNavBarExtra" label="extra navigation">
23
- <div v-if="localeLinks.length && currentLang.label" class="group translations">
22
+ <VPFlyout
23
+ v-if="hasExtraContent"
24
+ class="VPNavBarExtra"
25
+ label="extra navigation"
26
+ >
27
+ <div
28
+ v-if="localeLinks.length && currentLang.label"
29
+ class="group translations"
30
+ >
24
31
  <p class="trans-title">{{ currentLang.label }}</p>
25
32
 
26
33
  <template v-for="locale in localeLinks" :key="locale.link">
@@ -28,7 +35,14 @@ const hasExtraContent = computed(
28
35
  </template>
29
36
  </div>
30
37
 
31
- <div v-if="site.appearance && site.appearance !== 'force-dark'" class="group">
38
+ <div
39
+ v-if="
40
+ site.appearance &&
41
+ site.appearance !== 'force-dark' &&
42
+ site.appearance !== 'force-auto'
43
+ "
44
+ class="group"
45
+ >
32
46
  <div class="item appearance">
33
47
  <p class="label">
34
48
  {{ theme.darkModeSwitchLabel || 'Appearance' }}
@@ -7,10 +7,21 @@ const { theme } = useData()
7
7
  </script>
8
8
 
9
9
  <template>
10
- <nav v-if="theme.nav" aria-labelledby="main-nav-aria-label" class="VPNavBarMenu">
11
- <span id="main-nav-aria-label" class="visually-hidden">Main Navigation</span>
12
- <template v-for="item in theme.nav" :key="item.text">
10
+ <nav
11
+ v-if="theme.nav"
12
+ aria-labelledby="main-nav-aria-label"
13
+ class="VPNavBarMenu"
14
+ >
15
+ <span id="main-nav-aria-label" class="visually-hidden">
16
+ Main Navigation
17
+ </span>
18
+ <template v-for="item in theme.nav" :key="JSON.stringify(item)">
13
19
  <VPNavBarMenuLink v-if="'link' in item" :item="item" />
20
+ <component
21
+ v-else-if="'component' in item"
22
+ :is="item.component"
23
+ v-bind="item.props"
24
+ />
14
25
  <VPNavBarMenuGroup v-else :item="item" />
15
26
  </template>
16
27
  </nav>
@@ -12,15 +12,17 @@ const props = defineProps<{
12
12
  const { page } = useData()
13
13
 
14
14
  const isChildActive = (navItem: DefaultTheme.NavItem) => {
15
+ if ('component' in navItem) return false
16
+
15
17
  if ('link' in navItem) {
16
18
  return isActive(
17
19
  page.value.relativePath,
18
20
  navItem.link,
19
21
  !!props.item.activeMatch
20
22
  )
21
- } else {
22
- return navItem.items.some(isChildActive)
23
23
  }
24
+
25
+ return navItem.items.some(isChildActive)
24
26
  }
25
27
 
26
28
  const childrenActive = computed(() => isChildActive(props.item))
@@ -30,11 +32,9 @@ const childrenActive = computed(() => isChildActive(props.item))
30
32
  <VPFlyout
31
33
  :class="{
32
34
  VPNavBarMenuGroup: true,
33
- active: isActive(
34
- page.relativePath,
35
- item.activeMatch,
36
- !!item.activeMatch
37
- ) || childrenActive
35
+ active:
36
+ isActive(page.relativePath, item.activeMatch, !!item.activeMatch) ||
37
+ childrenActive
38
38
  }"
39
39
  :button="item.text"
40
40
  :items="item.items"
@@ -37,7 +37,7 @@ const isLocked = useScrollLock(inBrowser ? document.body : null)
37
37
  <style scoped>
38
38
  .VPNavScreen {
39
39
  position: fixed;
40
- top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);
40
+ top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));
41
41
  /*rtl:ignore*/
42
42
  right: 0;
43
43
  bottom: 0;
@@ -47,7 +47,7 @@ const isLocked = useScrollLock(inBrowser ? document.body : null)
47
47
  width: 100%;
48
48
  background-color: var(--vp-nav-screen-bg-color);
49
49
  overflow-y: auto;
50
- transition: background-color 0.5s;
50
+ transition: background-color 0.25s;
51
51
  pointer-events: auto;
52
52
  }
53
53
 
@@ -6,7 +6,14 @@ const { site, theme } = useData()
6
6
  </script>
7
7
 
8
8
  <template>
9
- <div v-if="site.appearance && site.appearance !== 'force-dark'" class="VPNavScreenAppearance">
9
+ <div
10
+ v-if="
11
+ site.appearance &&
12
+ site.appearance !== 'force-dark' &&
13
+ site.appearance !== 'force-auto'
14
+ "
15
+ class="VPNavScreenAppearance"
16
+ >
10
17
  <p class="text">
11
18
  {{ theme.darkModeSwitchLabel || 'Appearance' }}
12
19
  </p>
@@ -8,10 +8,13 @@ const { theme } = useData()
8
8
 
9
9
  <template>
10
10
  <nav v-if="theme.nav" class="VPNavScreenMenu">
11
- <template v-for="item in theme.nav" :key="item.text">
12
- <VPNavScreenMenuLink
13
- v-if="'link' in item"
14
- :item="item"
11
+ <template v-for="item in theme.nav" :key="JSON.stringify(item)">
12
+ <VPNavScreenMenuLink v-if="'link' in item" :item="item" />
13
+ <component
14
+ v-else-if="'component' in item"
15
+ :is="item.component"
16
+ v-bind="item.props"
17
+ screen-menu
15
18
  />
16
19
  <VPNavScreenMenuGroup
17
20
  v-else
@@ -10,8 +10,8 @@ const props = defineProps<{
10
10
 
11
11
  const isOpen = ref(false)
12
12
 
13
- const groupId = computed(() =>
14
- `NavScreenGroup-${props.text.replace(' ', '-').toLowerCase()}`
13
+ const groupId = computed(
14
+ () => `NavScreenGroup-${props.text.replace(' ', '-').toLowerCase()}`
15
15
  )
16
16
 
17
17
  function toggle() {
@@ -32,16 +32,17 @@ function toggle() {
32
32
  </button>
33
33
 
34
34
  <div :id="groupId" class="items">
35
- <template v-for="item in items" :key="item.text">
36
- <div v-if="'link' in item" :key="item.text" class="item">
35
+ <template v-for="item in items" :key="JSON.stringify(item)">
36
+ <div v-if="'link' in item" class="item">
37
37
  <VPNavScreenMenuGroupLink :item="item" />
38
38
  </div>
39
39
 
40
+ <div v-else-if="'component' in item" class="item">
41
+ <component :is="item.component" v-bind="item.props" screen-menu />
42
+ </div>
43
+
40
44
  <div v-else class="group">
41
- <VPNavScreenMenuGroupSection
42
- :text="item.text"
43
- :items="item.items"
44
- />
45
+ <VPNavScreenMenuGroupSection :items="item.items" />
45
46
  </div>
46
47
  </template>
47
48
  </div>
@@ -3,7 +3,7 @@ import { useScrollLock } from '@vueuse/core'
3
3
  import { inBrowser } from 'vitepress'
4
4
  import { ref, watch } from 'vue'
5
5
  import { useSidebar } from '../composables/sidebar'
6
- import VPSidebarItem from './VPSidebarItem.vue'
6
+ import VPSidebarGroup from './VPSidebarGroup.vue'
7
7
 
8
8
  const { sidebarGroups, hasSidebar } = useSidebar()
9
9
 
@@ -25,6 +25,16 @@ watch(
25
25
  },
26
26
  { immediate: true, flush: 'post' }
27
27
  )
28
+
29
+ const key = ref(0)
30
+
31
+ watch(
32
+ sidebarGroups,
33
+ () => {
34
+ key.value += 1
35
+ },
36
+ { deep: true }
37
+ )
28
38
  </script>
29
39
 
30
40
  <template>
@@ -37,17 +47,18 @@ watch(
37
47
  >
38
48
  <div class="curtain" />
39
49
 
40
- <nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1">
50
+ <nav
51
+ class="nav"
52
+ id="VPSidebarNav"
53
+ aria-labelledby="sidebar-aria-label"
54
+ tabindex="-1"
55
+ >
41
56
  <span class="visually-hidden" id="sidebar-aria-label">
42
57
  Sidebar Navigation
43
58
  </span>
44
59
 
45
60
  <slot name="sidebar-nav-before" />
46
-
47
- <div v-for="item in sidebarGroups" :key="item.text" class="group">
48
- <VPSidebarItem :item="item" :depth="0" />
49
- </div>
50
-
61
+ <VPSidebarGroup :items="sidebarGroups" :key="key" />
51
62
  <slot name="sidebar-nav-after" />
52
63
  </nav>
53
64
  </aside>
@@ -122,16 +133,4 @@ watch(
122
133
  .nav {
123
134
  outline: 0;
124
135
  }
125
-
126
- .group + .group {
127
- border-top: 1px solid var(--vp-c-divider);
128
- padding-top: 10px;
129
- }
130
-
131
- @media (min-width: 960px) {
132
- .group {
133
- padding-top: 10px;
134
- width: calc(var(--vp-sidebar-width) - 64px);
135
- }
136
- }
137
136
  </style>
@@ -0,0 +1,56 @@
1
+ <script setup lang="ts">
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
+ import { onBeforeUnmount, onMounted, ref } from 'vue'
4
+ import VPSidebarItem from './VPSidebarItem.vue'
5
+
6
+ defineProps<{
7
+ items: DefaultTheme.SidebarItem[]
8
+ }>()
9
+
10
+ const disableTransition = ref(true)
11
+
12
+ let timer: ReturnType<typeof setTimeout> | null = null
13
+
14
+ onMounted(() => {
15
+ timer = setTimeout(() => {
16
+ timer = null
17
+ disableTransition.value = false
18
+ }, 300)
19
+ })
20
+
21
+ onBeforeUnmount(() => {
22
+ if (timer != null) {
23
+ clearTimeout(timer)
24
+ timer = null
25
+ }
26
+ })
27
+ </script>
28
+
29
+ <template>
30
+ <div
31
+ v-for="item in items"
32
+ :key="item.text"
33
+ class="group"
34
+ :class="{ 'no-transition': disableTransition }"
35
+ >
36
+ <VPSidebarItem :item="item" :depth="0" />
37
+ </div>
38
+ </template>
39
+
40
+ <style scoped>
41
+ .no-transition :deep(.caret-icon) {
42
+ transition: none;
43
+ }
44
+
45
+ .group + .group {
46
+ border-top: 1px solid var(--vp-c-divider);
47
+ padding-top: 10px;
48
+ }
49
+
50
+ @media (min-width: 960px) {
51
+ .group {
52
+ padding-top: 10px;
53
+ width: calc(var(--vp-sidebar-width) - 64px);
54
+ }
55
+ }
56
+ </style>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
2
  import type { DefaultTheme } from 'vitepress/theme'
3
+ import { computed } from 'vue'
4
4
  import { useSidebarControl } from '../composables/sidebar'
5
5
  import VPLink from './VPLink.vue'
6
6
 
@@ -27,8 +27,8 @@ const textTag = computed(() => {
27
27
  return !hasChildren.value
28
28
  ? 'p'
29
29
  : props.depth + 2 === 7
30
- ? 'p'
31
- : `h${props.depth + 2}`
30
+ ? 'p'
31
+ : `h${props.depth + 2}`
32
32
  })
33
33
 
34
34
  const itemRole = computed(() => (isLink.value ? undefined : 'button'))
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { inject, computed } from 'vue'
2
+ import { inject, ref, watchPostEffect } from 'vue'
3
3
  import { useData } from '../composables/data'
4
4
  import VPSwitch from './VPSwitch.vue'
5
5
 
@@ -9,8 +9,10 @@ const toggleAppearance = inject('toggle-appearance', () => {
9
9
  isDark.value = !isDark.value
10
10
  })
11
11
 
12
- const switchTitle = computed(() => {
13
- return isDark.value
12
+ const switchTitle = ref('')
13
+
14
+ watchPostEffect(() => {
15
+ switchTitle.value = isDark.value
14
16
  ? theme.value.lightModeSwitchTitle || 'Switch to light theme'
15
17
  : theme.value.darkModeSwitchTitle || 'Switch to dark theme'
16
18
  })
@@ -242,8 +242,7 @@ vite-error-overlay {
242
242
  }
243
243
 
244
244
  mjx-container {
245
- display: inline-block;
246
- margin: auto 2px -2px;
245
+ overflow-x: auto;
247
246
  }
248
247
 
249
248
  mjx-container > svg {
@@ -35,6 +35,13 @@
35
35
  font-size: 20px;
36
36
  }
37
37
 
38
+ .vp-doc h4 {
39
+ margin: 24px 0 0;
40
+ letter-spacing: -0.01em;
41
+ line-height: 24px;
42
+ font-size: 18px;
43
+ }
44
+
38
45
  .vp-doc .header-anchor {
39
46
  position: absolute;
40
47
  top: 0;
@@ -98,12 +105,12 @@
98
105
  border-left: 2px solid var(--vp-c-divider);
99
106
  padding-left: 16px;
100
107
  transition: border-color 0.5s;
108
+ color: var(--vp-c-text-2);
101
109
  }
102
110
 
103
111
  .vp-doc blockquote > p {
104
112
  margin: 0;
105
113
  font-size: 16px;
106
- color: var(--vp-c-text-2);
107
114
  transition: color 0.5s;
108
115
  }
109
116
 
@@ -262,7 +269,8 @@
262
269
 
263
270
  .vp-doc h1 > code,
264
271
  .vp-doc h2 > code,
265
- .vp-doc h3 > code {
272
+ .vp-doc h3 > code,
273
+ .vp-doc h4 > code {
266
274
  font-size: 0.9em;
267
275
  }
268
276